From 417410ebac56f65dc19b699e0a486cd7620d7183 Mon Sep 17 00:00:00 2001
From: Neil Turton <nturton@gitlab.riscosopen.org>
Date: Tue, 9 Feb 1999 10:57:42 +0000
Subject: [PATCH] ROM speed not taken from the Machine header file.  POST can
 now exist in a softloaded OS, since it searches for a zero word in the ROM
 instead of using one within the POST when trying to communicate with the POST
 adapter (the zero word must be in ROM).  Fixed to build on non-chrontel
 STB/NC products.  Lots of duplicate code merged in

MemSize.  MemSize copes better with the softload case, and is less
willing to use the region the OS occupies as video memory, or
page tables.  POST is now ON (memory tests disabled).
OS_ReadSysInfo 4 now uses the NVRAM module to access the ethernet
address in NVRAM/CMOS, so that the availability/location of the
MAC address can be changed.  CMOS location 0 is now unprotected on
STB/NC products to try to stop people poking the hardware directly.
Fixed a CMOS resetting problem on STBs where the value expected in a
location was different from the value written on a CMOS reset, so the
CMOS would be reset every time...

Version 4.69. Tagged as 'Kernel-4_69'
---
 TestSrc/Begin |  14 +-
 TestSrc/ExtIO |  36 ---
 VersionASM    |   6 +-
 VersionNum    |  12 +-
 hdr/KernelWS  |   2 +-
 s/ARM600      | 686 +++++++++++++++++++++++++-------------------------
 s/GetAll      |   3 +-
 s/Middle      |  85 ++++---
 s/NewReset    |   4 +-
 s/PMF/osinit  |   2 +-
 10 files changed, 420 insertions(+), 430 deletions(-)

diff --git a/TestSrc/Begin b/TestSrc/Begin
index 2a303561..0d7287f4 100644
--- a/TestSrc/Begin
+++ b/TestSrc/Begin
@@ -707,9 +707,9 @@ ts_Self_test_startup ROUT
         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_5 :OR: IOMD_ROMCR_BTicks_4
+        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_5 :OR: IOMD_ROMCR_BTicks_4
+        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
@@ -758,9 +758,9 @@ ts_Self_test_startup ROUT
         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_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_$ROMSpeed_NSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     |
-        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeed_NSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
         STRB    r0, [r2, #IOMD_ROMCR0]          ; Prog. the reg.s
   [ CanLiveOnROMCard
@@ -1357,7 +1357,11 @@ Speedset
         ALIGN
 
 RAMtest
-        B       ts_VIDCtest	; skip memory test altogether; was	ADR     r4,%BT1
+ [ {TRUE}
+        B       ts_VIDCtest	; skip memory test altogether
+ |
+	ADR     r4,%BT1
+ ]
         BL      ts_SendText
 ;
 ; if (R_MEMSKIP && R_HARD)
diff --git a/TestSrc/ExtIO b/TestSrc/ExtIO
index 6115db36..cab813c2 100644
--- a/TestSrc/ExtIO
+++ b/TestSrc/ExtIO
@@ -83,23 +83,6 @@ ts_GetCommand  ROUT
 ;
 ; Load up the registers for the test interface communication -
 ;
-  [ :LNOT: CanLiveOnROMCard
-        LDR     r0,%01                  ; set zero in r0
-        ADD     pc,pc,r0  ;(generally useful constant - especially for skip)
-01
-        &       0
-        LDR     r1,%02                  ; set FFFFFFFF in r1
-        ADD     pc,pc,r0  ;(test value : sets carry when added to non-zero)
-02
-        &       (-1)
-        LDR     r2,%03                  ; set pointer to test address
-        ADD     pc,pc,r0  ;(points to aliased copy of a zero word)
-03
-        &       (ts_Alias_bits + (%01 - %04))
-        ADDS    r2,pc,r2                ; adjust r2 for ROM-relative address
-        ADDS    r4,r0,r0                ; clear output accumulator
-04                                      ; where pc is when added to r2
-  |
 ; Point r2 at a word which contains 0 in 0-8MB physical space.
 ; Note that this code doesn't cope with the case where it can't find a zero
 ; word anywhere in the whole ROM. I don't think that this is a problem.
@@ -114,7 +97,6 @@ ts_GetCommand  ROUT
 	ADD	r2, r2, #ts_Alias_bits	; point to zero word in ghost
 	MOV	r1, #-1			; expected below
 04
-  ]
         ; do an RD operation (four strobes) to ensure interface cleared
 
         LDR     r3,[r2]
@@ -629,23 +611,6 @@ ts_PosText      ROUT
 ;
 
 ts_SendLCDCmd
-  [ STB :LAND: :LNOT: CanLiveOnROMCard
-        LDR     r0,%01                  ; set zero in r0
-        ADD     pc,pc,r0
-01
-        &       0
-        LDR     r1,%02                  ; set FFFFFFFF in r1
-        ADD     pc,pc,r0  ;(test value : sets carry when added to non-zero)
-02
-        &       (-1)
-        LDR     r2,%03                  ; set pointer to test address
-        ADD     pc,pc,r0  ;(points to aliased copy of a zero word)
-03
-        &       (ts_Alias_bits + (%01 - %04))
-        ADDS    r2,pc,r2                ; adjust r2 for ROM-relative address
-        ADDS    r0,r0,r0                ; dummy (to keep labels nearby !)
-04                                      ; where pc points when added to r2
-  |
 ; Point r2 at a word which contains 0 in 0-8MB physical space.
 ; If this word still reads as 0 when its ghost/alias is read from 8-16MB space
 ; (A23 set) then we don't have a test box, otherwise we do.
@@ -661,7 +626,6 @@ ts_SendLCDCmd
 
 	ADD	r2, r2, #ts_Alias_bits	; point to zero word in ghost
 04
-  ]
 
 ; Wait - gap between successive WS attempts or successive bytes
 
diff --git a/VersionASM b/VersionASM
index 6f09e4c6..a2e4ada1 100644
--- a/VersionASM
+++ b/VersionASM
@@ -5,8 +5,8 @@
 			GBLA    Module_Version
 			GBLS	Module_MinorVersion
 			GBLS	Module_Date
-Module_MajorVersion	SETS    "4.68"
-Module_Version          SETA    468
+Module_MajorVersion	SETS    "4.69"
+Module_Version          SETA    469
 Module_MinorVersion	SETS	""
-Module_Date		SETS    "16 Dec 1998"
+Module_Date		SETS    "09 Feb 1999"
 		        END
diff --git a/VersionNum b/VersionNum
index 9e4a8657..39a27994 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,14 +1,14 @@
-/* (4.68)
+/* (4.69)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG     	4.68
+#define Module_MajorVersion_CMHG     	4.69
 #define Module_MinorVersion_CMHG	
-#define Module_Date_CMHG      		16 Dec 1998
+#define Module_Date_CMHG      		09 Feb 1999
 
-#define Module_MajorVersion     	"4.68"
-#define Module_Version                  468
+#define Module_MajorVersion     	"4.69"
+#define Module_Version                  469
 #define Module_MinorVersion		""
-#define Module_Date      		"16 Dec 1998"
+#define Module_Date      		"09 Feb 1999"
 
diff --git a/hdr/KernelWS b/hdr/KernelWS
index cbc42b31..e6c1dda5 100644
--- a/hdr/KernelWS
+++ b/hdr/KernelWS
@@ -660,7 +660,7 @@ VIDCClockSpeed # 4      ; current VIDC clock speed in kHz
 
 CurrentMonitorType # 4  ; initialised from configured one
 
- [ ChrontelSupport
+ [ STB
 PixelRate # 4   ; Pixel Rate in kHz
  ]
 
diff --git a/s/ARM600 b/s/ARM600
index d888ee7a..22119a00 100644
--- a/s/ARM600
+++ b/s/ARM600
@@ -989,9 +989,9 @@ init7500FEcpu
         ORR     r0, r0, #IOMD_ROMCR_HalfSpeed + IOMD_ROMCR_NSTicks_5 + IOMD_ROMCR_BTicks_3
   |
     [ ROMSpeedNormal
-        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        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_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
   ]
         STRB    r0, [r12, #IOMD_ROMCR0]         ; Prog. the reg.s
@@ -1070,9 +1070,9 @@ init7500cpu
         ORR     r0, r0, #IOMD_ROMCR_Normal + IOMD_ROMCR_NSTicks_5 + IOMD_ROMCR_BTicks_3
   |
     [ ROMSpeedNormal
-        ORR     r0, r0, #IOMD_ROMCR_Normal :OR: IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_BTicks_4
+        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_5 :OR: IOMD_ROMCR_BTicks_4
+        ORR     r0, r0, #IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_NSTicks_$ROMSpeedNSTicks :OR: IOMD_ROMCR_BTicks_$ROMSpeedBurstTicks
     ]
   ]
         STRB    r0, [r12, #IOMD_ROMCR0]          ; Prog. the reg.s
@@ -1409,8 +1409,6 @@ CommonInit
 ; 256Kbyte       4K          32*64kx1        A13,A20,A12,A18 fail, A21,A19 ok
 ;
 
-Z_Flag     * &40000000
-
 ; MemSize routine... enter with 32K pagesize set
 ; R0 returns page size
 ; R1 returns memory size
@@ -1462,14 +1460,6 @@ MemSize ROUT
   ]
         MOV     r14, #IOMD_Base
         STRB    r11, [r14, #IOMD_DRAMWID]
-
- [ 1 = 0
-        MOV     R10, #DRAM0PhysRam
-        MOV     R11, #(2*OneMByte)
-        STMIA   R10!, {R10, R11}
-        B       AllocateTheRAM
-        ! 0, "*** WARNING *** Bodged RAM sizing version ment for PSwindell"
- ]
         MOV     r10, #0                                 ;indicate no RAM found yet
         MOV     r9, #IOMD_DRAMWID_DRAM_16bit            ;bit to OR into DRAMWID to set 16bit
         MOV     r0, #DRAM0PhysRam
@@ -1490,259 +1480,53 @@ ExamineDRAMBank                                         ;examine first/next DRAM
         EOR     r6, r6, r4                              ; if memory is 32bits wide
        ;TEQ     r5, #0
         TEQEQ   r6, #0
-        BEQ     %FT1010                                   ;32bit wide memory
+        BEQ     %FT05                                   ;32bit wide memory
 
         TST     r5, #&00FF                              ;If the bottom 16bits of each location
         TSTEQ   r5, #&FF00                              ; are correct, the memory is 16bits wide
         TSTEQ   r6, #&00FF
         TSTEQ   r6, #&FF00
+        ADDNE   r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
         BNE     NoRamInBank                             ;No memory in this bank
 
         ORR     r11, r11, r9                            ;Bank is 16bits wide
-1010
+05
         STMIA   r0, {r1, r2}                            ;Restore the two locations we widdled on
                                                         ;Must do BEFORE poking the DRAMWID register
         MOV     r14, #IOMD_Base                         ;
         STRB    r11, [r14, #IOMD_DRAMWID]               ;
-;
-; minimum ram test
-;
-        ADD     r1, r0, #A18
-        BL      DistinctAddresses
-        BNE     NoRamInBank                             ;Less than 512KBytes, so ignore this bank
-
-        MOV     r6, #0                                  ;Fragment address
-        MOV     r7, #0                                  ;Fragment address
-        MOV     r8, #A19                                ; now go through address lines A19-A25
-1015
-        ADD     r1, r0, r8                              ; see if this address line is unique
-        BL      DistinctAddresses
-        BNE     %FT1020                                   ; 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     %BT1015
-        BEQ     %FT1035                           ;Bank fully occupied, DON'T test for higher fragments
-1020
-;
-; Found some DRAM, at address r0, size r8.
-; There may be one or two higher address lines connected, so scan upto A25 looking for
-; extra DRAM chunks.
-;
-        MOV     r1, r8
-1025
-        TEQ     r1, #A25
-        BEQ     %FT1035                           ;No higher active address lines found ie one lump of DRAM
-        ADD     r1, r0, r1,LSL #1
-        BL      DistinctAddresses
-        SUB     r1, r1, r0                              ;Recover bit value
-        BNE     %BT1025
-;
-; Got a 2nd fragment, at address r1 (also of size r8)
-;
-        MOV     r6, r1
-1030
-        TEQ     r1, #A25
-        BEQ     %FT1035                           ;No higher active address lines found ie two lumps of DRAM
-        ADD     r1, r0, r1,LSL #1
-        BL      DistinctAddresses
-        SUB     r1, r1, r0                              ;Recover bit value
-        BNE     %BT1030
-;
-; Got another active address line (ie total four fragments)
-;
-        MOV     r7, r1
-;
-1035
-;
-; Found 1, 2 or 4 lumps of DRAM
-;
-  [ 1 = 1
-;
-; New code which relies on reflection to merge fragments into larger blocks
-;
-        TEQ     r10, #0                         ;Need some ram to dump block/fragment data
-        MOVEQ   r10, r0                         ;
-
-        TEQ     r6, #0                          ;Do we have one fragment?
-        MOVEQ   r1, r0                          ;EQ: First and only fragment in this bank
-        MOVEQ   r2, r8                          ;EQ:   so save actual address and size
-        ADDNE   r1, r0, r6                      ;NE: Use reflection to make 1st fragment appear
-        SUBNE   r1, r1, r8                      ;NE:   to start just below 2nd fragment
-        MOVNE   r2, r8, LSL #1                  ;NE:   treat as one double size fragment
-
-        STMIA   r10!, {r1, r2}                  ; {address, size}
-
-        TEQ     r7, #0                          ;Do 3rd and 4th fragments exist
-        ADDNE   r1, r1, r7                      ;NE: yes, merge 3 and 4 together
-        STMNEIA r10!, {r1, r2}                  ;  {address, size}
-  |
-;
-; Old code which enters each fragment as found
-;
-        TEQ     r10, #0                         ;Need some ram to dump block/fragment data
-        MOVEQ   r10, r0                         ;
-
-        STMIA   r10!, {r0, r8}                  ;First fragment
-
-        TEQ     r6, #0
-        ADDNE   r1, r0, r6
-        STMNEIA r10!, {r1, r8}                  ;Second fragment
-
-        TEQ     r7, #0
-        ADDNE   r1, r0, r7
-        STMNEIA r10!, {r1, r8}                  ;Third
-        ADDNE   r1, r1, r6
-        STMNEIA r10!, {r1, r8}                  ;and fourth fragments
-  ]
-  [ Simulator
-        TubeString r2, r3, r4, "Address  Size"
-        TubeDumpNoStack r0, r2, r3, r4
-        TubeDumpNoStack r8, r2, r3, r4
-        TubeNewlNoStack r3, r4
-
-        TEQ     R7, #0
-        BEQ     skip1
-        TubeString r2, r3, r4, "Fragment (1): "
-        TubeDumpNoStack r7, r2, r3, r4
-        TubeNewlNoStack r3, r4
-skip1
-        TEQ     R6, #0
-        BEQ     skip2
-        TubeString r2, r3, r4, "Fragment (2): "
-        TubeDumpNoStack r6, r2, r3, r4
-        TubeNewlNoStack r3, r4
-skip2
-  ]
-
 
+        BL	Add_DRAM_bank
 
 NoRamInBank
-        ADD     r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
         MOV     r9, r9, LSL #1                          ; shunt up position in DRAMWID
         CMP     r9, #&0010                              ; if more banks to do
         BLT     ExamineDRAMBank                         ; then loop
 
-        TEQ     r10, #0                                 ; have we got any DRAM?
-;NoDRAMPanic
-        BEQ     NoDRAMPanic                             ; we'd better stop now
-
-;
-; Having dumped our block/fragment data to the first bit of DRAM that we found.
-; We now go back through it, allocating some for the screen, and some for 'PageZero'.
-; The data has been dumped into RAM that we now allocate as screen ram, so it needs
-; to be copied into 'PageZero'.
-;
-; r10 -> byte after last fragment(address, size) pair
-;
-AllocateTheRAM
-        AND     r7, r10, #DRAMBaseAddressMask           ;point to first fragment data
-        MOV     r2, #0                                  ;MOS workspace not yet allocated
-
-        LDMIA   r7!, {r4, r5}                           ;first fragment address & size
-        CMP     r10, r7                                 ;is there only 1 fragment
- [ 1 = 1
-;
-; New - requested by Tim Dobson
-;
-        MOVHI   r1, r5                                  ;if >1 fragments, take first fragment for the screen
-        SUBLS   r1, r5, #OneMByte                       ;if this is the only fragment, take all but 1MByte of it
-        MOV     r0, r4                                  ;screen starts at beginning of fragment
-  [ 1 = 1
-;
-; New - also requested by Tim Dobson
-;
-        CMP     r1, #SixteenMByte                       ;Limit our claim to 16Mbyte
-        MOVGT   r1, #SixteenMByte
-  ]
- |
-        MOVHI   r1, r5                                  ;if >1 fragments, consider taking first fragment for the screen
-        MOVLS   r1, r5, LSR #1                          ;if this is the only fragment, try for half of it
-        MOV     r0, r4                                  ;screen starts at beginning of fragment
-
-        CMP     r1, #OneMByte                           ;Limit our claim to 1Mbyte
-        MOVGT   r1, #OneMByte
- ]
-        ADD     r4, r4, r1                              ;adjust fragment for amount claimed by screen
-        SUBS    r5, r5, r1
-        BEQ     %FT1065                                 ;EQ whole fragment used
-                                                        ;NE part of fragment remains to be allocated
-1060
-        TEQ     r2, #0                                  ;allocate MOS workspace if not already done so
-        LDREQ   r2, =DRAMOffset_PageZero + DRAMPhysAddrA
-        ADDEQ   r2, r2, r4
-        MOVEQ   r3, r2
-
-        STMIA   r3!, {r4, r5}                           ;write fragment data to correct place in PageZero
-1065
-        CMP     r10, r7                                 ;any more fragment (address, size) pairs?
-        LDMHIIA r7!, {r4, r5}                           ;HI, yes so load next fragment pair (size
-        BHI     %BT1060                                 ;HI, mustbe non-zero) and loop back
-
-        STMDB   r2!, {r0, r1}                           ;write VideoPhysAddr, VideoSize
-;
-; r2 -> start of PhysRamTable
-; r3 -> byte after last used entry in PhysRamTable
-;
-        MOV     r7, r2
-       ;MOV     r2, r2                                  ; r2 -> start of PhysRamTable
-        MOV     r10, r3
-       ;MOV     r3, r3                                  ; r3 -> byte after last used entry in PhysRamTable
-
-
-;
-; r0 screen start address
-; r1 screen size
-; r2 -> start of PhysRamTable
-; r3 -> byte after last used entry in PhysRamTable
-
-        MOV     r4, #0                                  ;Morris cannot support VRAM, so...
-        STR     r4, [r2, #VRAMWidth-PhysRamTable]       ; store width of VRAM (0,1 or 2)
-        STR     r4, [r2, #VRAMSize-PhysRamTable]        ; and size of VRAM (fixes DForth's bug of 6/3/95)
-
+	MOV	r6, #0					; No VRAM
+	MOV	r0, #0
         MOV     r14, #IOMD_Base
 
-        MOV     r4, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
-        STRB    r4, [r14, #IOMD_VIDCR]
-        STR     r0, [r14, #IOMD_VIDCUR]                 ; set up VIDCUR to start of video RAM
-        STR     r0, [r14, #IOMD_VIDSTART]               ; do same for VIDSTART
-        STR     r0, [r14, #IOMD_VIDINIT]                ; and for VIDINIT
-                                                        ; so we don't get a mess when we turn video DMA on later
-
-
 	LDRB	r4, [r14, #IOMD_ID0]
 	LDRB	r7, [r14, #IOMD_ID1]
 	ORR	r4, r4, r7, LSL #8
 	LDR	r7, =IOMD_7500FE			; if FE part, then assume EDO DRAM
 	TEQ	r4, r7
-	LDREQ	r4, =80000000				; so allow 80E6 bytes/s
+	LDREQ	r2, =80000000				; so allow 80E6 bytes/s
  [ STB
-	LDRNE	r4, =44000000				; else only allow 44E6 bytes/s
+	LDRNE	r2, =44000000				; else only allow 44E6 bytes/s
  |
-        LDRNE   r4, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
+        LDRNE   r2, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
  ]
-        STR     r4, [r2, #VideoBandwidth-PhysRamTable]  ; store video bandwidth
-
-        ADD     r4, r0, r1                              ;form VIDEND (will be on mult. of SAM)
-        SUB     r4, r4, #4096
-        STR     r4, [r14, #IOMD_VIDEND]                 ;this instruction put in on 6/3/95 after inspection of RPC code
-;
-;
-;
-        MOV     r7, r2
-        MOV     r10, r3
+	MOV	r1, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
 
-        B       MemSizeTotalRAM
+        B       Allocate_DRAM
 
 MemSizeIOMD
  ]
 
 ; Right, let's find out where our memory is
 
-; First, we check out the VRAM. This is so that if there's no VRAM, we know to take out the 1st Mbyte of DRAM
-; that we find.
-
-; Don't bother checking for more than 2M of VRAM, because we don't know what the 1/2 SAM length is for larger sizes
-
 ; StrongARM - aha! but we still have no nice MMU, nor even fast core clock, and this memory sizing type
 ; stuff is going to be very slow for large memory. So turn on I cache (allowed with MMU off), and fast
 ; core clock now - this is then ok until MMU etc comes on (near CritStart)
@@ -1772,29 +1556,6 @@ MemSizeIOMD_notSA
     ]
 MemSizeIOMD_not810
   ]
-        MOV     r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default
-        STRB    r2, [r12, #IOMD_VREFCR]
-
-        MOV     r0, #VideoPhysRam                       ; point at VRAM
-        ADD     r1, r0, #A2                             ; test A2
-        BL      DistinctAddresses
-        MOVEQ   r6, #2                                  ; we've got 2M of VRAM
-        BEQ     %FT08
-
-        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   r6, #1                                  ; we've got 1M of VRAM
-        MOVNE   r6, #0                                  ; no VRAM
-08
- [ IgnoreVRAM
-        MOV     r6, #0                                  ; pretend there's no VRAM
- ]
-        MOVS    r12, r6                                 ; if no VRAM, then video RAM has yet to be found
-        MOVNE   r12, r0                                 ; else point at VRAM
-
-; Now, we have to find a bank of DRAM, so we've got somewhere to store our results!
 
         MOV     r11, #IOMD_DRAMCR_DRAM_Large * &55      ; set all banks to be large initially
         MOV     r14, #IOMD_Base
@@ -1806,81 +1567,115 @@ MemSizeIOMD_not810
 10
         ADD     r1, r0, #A10                            ; this should be OK for both configurations
         BL      DistinctAddresses
-        BNE     %FT25                                   ; [no RAM in this bank at all]
+        ADDNE   r0, r0, #DRAM1PhysRam-DRAM0PhysRam      ; move onto next bank
+        BNE     %FT15                                   ; [no RAM in this bank at all]
 
         ADD     r1, r0, #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     %FT20
 
-; 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
+	BL	Add_DRAM_bank
 
-        MOV     r8, #A21                                ; now go through address lines A21-A25
+; Now, we have to find a bank of DRAM, so we've got somewhere to store our results!
 15
-        ADD     r1, r0, r8                              ; see if this address line is unique
-        BL      DistinctAddresses
-        BNE     %FT20                                   ; 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     %BT15
-20
-        TEQ     r12, #0                                 ; have we found any video RAM yet?
-        BNE     %FT22                                   ; yes, so no worries
-
-        MOV     r12, r0                                 ; no, so use this as video RAM
-        ADD     r0, r0, #1024*1024                      ; advance RAM pointer by 1M
-        SUBS    r8, r8, #1024*1024                      ; take 1 Mbyte off the size
-        BEQ     %FT25                                   ; if that's all there was, then go look for the next bank
-22
-        TEQ     r10, #0                                 ; is this the first lot we've found?
-        LDREQ   r10, =DRAMOffset_PageZero + DRAMPhysAddrA
-        ADDEQ   r10, r10, r0                            ; then point r10 at DRAM part of PhysRamTable
-        MOVEQ   r7, r10                                 ; points to beginning of table
-        STMIA   r10!, {r0, r8}                          ; store address, size
-25
-        AND     r0, r0, #DRAMBaseAddressMask            ; move back to start of DRAM bank (in case we stole some video DRAM)
-        ADD     r0, r0, #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     %BT10                                   ; then loop
 
-        TEQ     r10, #0                                 ; have we got any DRAM?
+; Now, we check out the VRAM.
+; Don't bother checking for more than 2M of VRAM, because we don't know what the 1/2 SAM length is for larger sizes
+
+        MOV     r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default
+        STRB    r2, [r12, #IOMD_VREFCR]
+
+        MOV     r0, #VideoPhysRam                       ; point at VRAM
+        ADD     r1, r0, #A2                             ; test A2
+        BL      DistinctAddresses
+        MOVEQ   r6, #2                                  ; we've got 2M of VRAM
+        BEQ     %FT20
+
+        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   r6, #1                                  ; we've got 1M of VRAM
+        MOVNE   r6, #0                                  ; no VRAM
+20
+ [ IgnoreVRAM
+        MOV     r6, #0                                  ; pretend there's no VRAM
+ ]
+        CMP     r6, #1
+        MOVCC   r1, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
+        MOVEQ   r1, #SAMLength/2/256                    ; if 1M VRAM, then use VRAM mode, and set increment for 1/2 SAM
+        MOVHI   r1, #SAMLength/2/256*2                  ; if 2M VRAM, then use VRAM mode, and set increment for 2*1/2 SAM
+        LDRCC   r2, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
+        LDREQ   r2, =80000000                           ; if 1M VRAM, then 80E6   ---------""--------
+        LDRHI   r2, =160000000                          ; if 2M VRAM, then 160E6  ---------""--------
+	MOVCC	r0, #0					; Clear VRAM base if there is no VRAM
+
+; Allocate_DRAM
+;   r0  = Video base if r6!=0
+;   r1  = Value for IOMD VIDCR
+;   r2  = Bandwidth limit
+;   r6  = VRAM size in Mb
+;   r10 = End of DRAM list
+Allocate_DRAM
+
 NoDRAMPanic
-        BEQ     NoDRAMPanic                             ; we'd better stop now
+	TST	r10, r10
+	BEQ	NoDRAMPanic				; Stop here if there is no DRAM (we could use VRAM I suppose...)
+
+	MOV	r7, r6, LSL #20				; r7 = size of video memory
+	LDR	r8, [r10]				; r8 = the number of DRAM blocks.
+	SUB	r11, r10, r8, LSL #3			; Jump back to the start of the list
+
+	LDMIA	r11!, {r4, r5}				; Get a block from the list. (r4,r5) = (base,size)
+	CMP	r6, #0					; Did we find any VRAM?
+	BNE	%FT30					; Skip this bit if we did.
+	MOV	r0, r4					; Allocate this block as video memory
+	MOV	r7, r5
+	CMP	r10, r11				; Was this the only block?  If so, leave 1M
+	SUBEQS	r7, r7, #1024*1024
+	MOVCC	r7, r5, ASR #1				; If that overflowed, take half the bank.
+	CMP	r7, #16*1024*1024
+	MOVCS	r7, #16*1024*1024			; Limit allocation to 16M - the size of the logical space
+
+	ADD	r4, r4, r7				; Adjust the DRAM block base...
+	SUBS	r5, r5, r7				; ... and the size.
+	LDMEQIA	r11!, {r4, r5}				; Fetch the next block if we claimed it all.
+
+30	ADD	r12, r4, #DRAMOffset_PageZero		; Use the first block for kernel workspace.
+	ADD	r3, r12, #DRAMPhysAddrA			; Set the table address as well
+
+	CMP	r8, #5
+	ADDCS	r10, r11, #3:SHL:3			; Limit to 4 blocks of DRAM (3 + this one)
+
+35	STMIA	r3!, {r4, r5}				; Put the DRAM block into the table
+	TEQ	r10, r11
+	LDMNEIA	r11!, {r4, r5}				; Get the next block if there is one.
+	BNE	%BT35
 
 ; Now go back and put the VRAM information in, and also program VIDCR and VIDCUR
 
-        STR     r6, [r7, #VRAMWidth-DRAMPhysAddrA]      ; store width of VRAM (0,1 or 2)
-        CMP     r6, #1
-        MOVCC   r2, #IOMD_VIDCR_DRAMMode :OR: &10       ; if no VRAM, then turn on DRAM mode, and set increment to &10
-        MOVEQ   r2, #SAMLength/2/256                    ; if 1M VRAM, then use VRAM mode, and set increment for 1/2 SAM
-        MOVHI   r2, #SAMLength/2/256*2                  ; if 2M VRAM, then use VRAM mode, and set increment for 2*1/2 SAM
-        LDRCC   r3, =46500000                           ; if no VRAM, then 46.5E6 bytes/sec bandwidth
-        LDREQ   r3, =80000000                           ; if 1M VRAM, then 80E6   ---------""--------
-        LDRHI   r3, =160000000                          ; if 2M VRAM, then 160E6  ---------""--------
+        STR     r6, [r12, #VRAMWidth]                   ; store width of VRAM (0,1 or 2)
         MOV     r14, #IOMD_Base
-        STRB    r2, [r14, #IOMD_VIDCR]
-        STR     r12, [r14, #IOMD_VIDCUR]                ; set up VIDCUR to start of video RAM
-        STR     r12, [r14, #IOMD_VIDSTART]              ; do same for VIDSTART
-        STR     r12, [r14, #IOMD_VIDINIT]               ; and for VIDINIT
+        STRB    r1, [r14, #IOMD_VIDCR]
+        STR     r0, [r14, #IOMD_VIDCUR]                 ; set up VIDCUR to start of video RAM
+        STR     r0, [r14, #IOMD_VIDSTART]               ; do same for VIDSTART
+        STR     r0, [r14, #IOMD_VIDINIT]                ; and for VIDINIT
                                                         ; so we don't get a mess when we turn video DMA on later
-        STR     r3, [r7, #VideoBandwidth-DRAMPhysAddrA] ; store video bandwidth
-
-        ADD     r3, r12, #1024*1024-4096                ; add on a bit to form VIDEND (will be on mult. of SAM)
-        STR     r3, [r14, #IOMD_VIDEND]                 ; yes I know it's a bit of a bodge
+        STR     r2, [r12, #VideoBandwidth]              ; store video bandwidth
 
-        MOVS    r14, r6, LSL #20                        ; convert amount of VRAM to bytes
-        STR     r14, [r7, #VRAMSize-DRAMPhysAddrA]      ; and store
+        ADD     r4, r0, #1024*1024-4096                 ; add on a bit to form VIDEND (will be on mult. of SAM)
+        STR     r4, [r14, #IOMD_VIDEND]                 ; yes I know it's a bit of a bodge
 
-        MOVEQ   r14, #1024*1024                         ; if no VRAM, then video RAM size is 1M
-        STMDB   r7!, {r12, r14}                         ; store video information
+        MOV     r4, r6, LSL #20                         ; convert amount of VRAM to bytes
+        STR     r4, [r12, #VRAMSize]                    ; and store
 
-        MOV     r2, r7                                  ; r2 -> start of PhysRamTable
-        MOV     r3, r10                                 ; r3 -> byte after last used entry in PhysRamTable
+	ADD	r2, r12, #VideoPhysAddr			; r2 -> Start of PhysRamTable
+        STMIA   r2, {r0, r7}                            ; store video memory block
 MemSizeTotalRAM
 ; Now we have to work out the total RAM size
 
@@ -1888,7 +1683,8 @@ MemSizeTotalRAM
         TubeString r4, r5, r6, "Address  Size"
   ]
         MOV     r1, #0
-26
+        MOV     r7, r2
+40
         LDMIA   r7!, {r4, r5}                           ; get address, size
         ADD     r1, r1, r5                              ; add on size
   [ Simulator
@@ -1896,11 +1692,13 @@ MemSizeTotalRAM
         TubeDumpNoStack r5, r6, r8, r9
         TubeNewlNoStack r6, r8
   ]
-        TEQ     r7, r10
-        BNE     %BT26
+        TEQ     r7, r3
+        BNE     %BT40
 
         MOV     r0, #Page4K                             ; something to put in MEMC CR soft copy
                                                         ; (it's probably irrelevant)
+	ADRL	r4, ROM
+
  |
 
 ; MEMC based memory sizing
@@ -1985,7 +1783,6 @@ MemSizeDone
 
         LDR     r4, =38400000                   ; indicate 38.4E6 bytes/sec video bandwidth
         STR     r4, [r2, #VideoBandwidth-PhysRamTable]
- ]
 
         ADRL    r4, ROM                         ; use PC-relative addressing to get to start of image
         TEQ     r4, #PhysROM                    ; then see if it's the normal ROM address
@@ -2047,6 +1844,14 @@ MemSizeDone
         STMIA   r8, {r5, r9}                    ; store end lump
         ADD     r3, r3, #8                      ; advance end pointer
 
+ ]
+
+; r0 = Page size
+; r1 = Total memory size (bytes)
+; r2 = PhysRamTable
+; r3 = After last used entry in PhysRamTable
+; r4 = Address of ROM
+
 ; now store zeros to fill out table
 
 55
@@ -2268,6 +2073,188 @@ CritEnd                                         ; 2 words after we go up into RO
  ]
         MOV     pc, r13
 
+ [ MEMC_Type = "IOMD"
+; add_dram_bank
+;   Entry: r10 -> workspace (initially 0)
+;          r0  =  bank address
+;   Exit:  r10 -> workspace (allocated if 0 on entry)
+;          r0  =  next bank address
+;          r9, r11, r13 preserved
+;   Probe a DRAM bank, and add any DRAM found to the workspace
+Add_DRAM_bank
+	ROUT
+	MOV	r12, lr			; r12 = return address
+	EOR	r1, r0, #A16		; Check there is some RAM in the bank
+	BL	DistinctAddresses
+	ADDNE	r0, r0, #DRAM1PhysRam-DRAM0PhysRam
+	MOVNE	pc, r12			; Return if no RAM in the bank
+
+	; Only some address lines are decoded by the SIMM.  For example, a 4M SIMM may be split
+	; into 2 banks, with A2-A20 decoded on each, or A2-A19,A21 decoded.  First we need to
+	; find out which address lines are decoded, and which are ignored.
+	MOV	r6, #DRAM1PhysRam-DRAM0PhysRam
+	MOV	r7, #A17
+	SUB	r6, r6, #1		; Get address lines which select address within bank.
+
+	; Loop through the address lines, finding out which are decoded.  We clear the bits in r6
+	; which correspond to non-decoded address lines.
+	; r6 = address line mask
+	; r7 = current address line
+10	EOR	r1, r0, r7		; Toggle the address line
+	BL	DistinctAddresses	; Check if address line has any effect.
+	BICNE	r6, r6, r7		; Clear the bit if the address line fails.
+	MOV	r7, r7, LSL #1		; Move onto the next address line.
+	TST	r6, r7			; Have we reached the limit?
+	BNE	%BT10			; Repeat if not.
+
+	; r6 = decoded address lines in bank. (ie in A0-A25)
+	; r7 = The size of the DRAM bank
+	; Since the DRAM bank may not be contiguous, we now split the bank up into contiguous
+	; blocks.  We make these as large as possible to save work.  Here we set r8 to the
+	; size of the smallest contiguous block(s) of RAM.  (There will also be some contiguous
+	; blocks which are twice this size in some cases.)
+	ADD	r8, r6, #A17
+	BIC	r8, r8, r6		; r8 = First clear bit in r6 from A17 up.
+
+	RSB	r4, r8, #0		; r4 = All bits at or above r8 set since r8 is a power of 2.
+
+	RSB	r7, r7, #0		; r7 = address bits which select the bank since r7 was a
+					;      power of 2.
+	ORR	r3, r7, r6		; r3 = All decoded address lines.
+	AND	r7, r4, r3		; r7 = All decoded bits at or above r8.
+
+; Make sure that the dram bank may not be contained within the image.  The code below fails
+; to work correctly if a dram bank is contained within an OS image.  Currently this would
+; require an image larger than 64M.
+		ASSERT	OSROM_ImageSize*1024 <= DRAM1PhysRam-DRAM0PhysRam
+
+15	MOV	r1, r0			; r1 = Address of start of block (inclusive).
+	ADD	r2, r1, r8		; r2 = End of the block (exclusive).
+
+	; Move the end of the block if the OS image begins in this block.
+	ADRL	r4, ROM			; r4 = Start of the OS image (which may be in RAM).
+	EOR	r5, r4, r1		; r5 = Difference between image and memory block.
+	TST	r5, r7			; Check if the image begins in this block of RAM.
+	ANDEQ	r2, r4, r3		; Set end of block to start of image.
+
+	; Move the start of the block if the OS image ends in this block.
+	ADD	r4, r4, #OSROM_ImageSize*1024
+	SUB	r4, r4, #1		; r4 = Last byte of the OS image.
+	EOR	r5, r4, r1		; r5 = Difference between end of image and block.
+	TST	r5, r7			; Check if the image ends in this block of RAM.
+	ANDEQ	r5, r4, r3		; r5 = Address of last byte of the image within this block.
+	ADDEQ	r1, r5, #1		; Set start of block to the byte after the image.
+
+	; If the image is contained in the block, we will have swapped the start and end
+	; addresses.  This means that the block is split into two parts.  The bit below
+	; the image and the bit above the image.
+	CMP	r1, r2
+	BLS	%FT20			; If start <= end, then block is not fragmented.
+	CMP	r2, r0			; Check the size of the fragment before the image.
+	MOV	r0, r1			; Store old start address
+	AND	r1, r1, r7		; Get the start of the block
+	BLNE	Allocate_DRAM_fragment	; Allocate it if it's non-zero.
+	MOV	r1, r0			; Restore the old start of fragment
+	AND	r0, r0, r7		; Get the start of the block again.
+	ADD	r2, r0, r8		; End of next fragment is the end of the block.
+
+	CMP	r1, r2			; Compare start and (modified) end.
+20	BLNE	Allocate_DRAM_fragment
+
+	; Now move onto the next block.  We add the non-decoded address lines to cause the
+	; carry to be propagated across them.  Then we mask them out.
+	MVN	r4, r7			; Add the non-connected address lines to ...
+	ADD	r4, r4, r0		; ... the block address ...
+	ADD	r4, r4, r8		; ... and the block size.
+;	EOR	r5, r0, r4		; Compare with old address
+	AND	r0, r4, r7		; Leave only the decoded lines set.
+;	BIC	r5, r5, r6		; Clear decoded lines within the bank.
+;	TST	r5, r7			; Check only the bank lines.
+;	BEQ	%BT15			; Repeat for next block.
+
+	TST	r0, r6
+	BNE	%BT15
+
+	MOV	pc, r12			; Done for this bank.
+
+; Allocate_DRAM_block
+;   Entry:
+;     r1 = block start (inclusive)
+;     r2 = block end (exclusive)
+;     r3 = All decoded address lines
+;     r7 = All decoded bits at or above r8
+;     r8 = Size of largest contiguous block
+;     block length is assumed to be at least the size of the static data - ie. 160k
+;     The maximum block list size is then 4k, which fits easily into the cursor chunk
+;   Exit:
+;     r10 updated
+;     r0, r3, r6-r9, r11-r13 preserved
+;     r10 points to a word containing the number of blocks stored.
+;     The pairs of words before
+Allocate_DRAM_fragment
+	ROUT
+	CMP	r10, #0
+	BEQ	%FT20
+
+	; We are not dealing with the first block since r10 != 0.  Make an attempt to merge this block
+	; with the previous block.
+	LDMDB	r10, {r4, r5}		; Get details of the previous block
+	ADD	r5, r4, r5		; Get the end address
+	EOR	r5, r5, r1		; Compare with the current block start address...
+	TST	r5, r3			; ... but only check the decoded bits.
+	EOR	r5, r5, r1		; Restore the previous block end address.
+	BNE	%FT10			; We can't merge it after the previous block
+
+	; r4 = previous start
+	; r5 = previous end
+	; The block is just after the previous block.  That means the start address is unchanged, but
+	; the length is increased.
+	SUB	r5, r5, r4		; Calculate the previous block length.
+	SUB	r2, r2, r1		; Find the length of the new block.
+	; r2 = length of block
+	ADD	r5, r5, r2		; Add it to the previous length.
+	STR	r5, [r10, #-4]		; Update the block size in memory.
+	MOV	pc, lr
+
+	; The block is not just after the previous block, but it may be just before.  This may be the
+	; case if we are softloaded.
+10	SUB	r4, r4, #1		; Compare the address before the previous block start ...
+	SUB	r2, r2, #1		; ... with the address of the last byte in this block ...
+	EOR	r4, r4, r2
+	TST	r4, r3			; ... but check only the decoded bits.
+	ADD	r2, r2, #1		; Restore the end address.
+	BNE	%FT20			; Skip if we cannot merge the block.
+
+	; The block is just before the previous block.  The start address and length both change.
+	LDR	r4, [r10, #-8]		; Get the previous block start again.
+
+	SUB	r2, r2, r1		; Calculate the current block size.
+	SUB	r4, r4, r2		; Subtract from the previous block start address.
+	SUB	r5, r5, r4		; Calculate the new length=end-start
+	STMDB	r10, {r4, r5}		; Update the block info in memory.
+	MOV	pc, lr
+
+	; We now have a region which does not merge with a previous region.  We move it up to the
+	; highest address we can in the hope that this block will merge with the next block.
+20	SUB	r2, r2, r1		; Calculate the block size
+	MVN	r4, r3			; Get the non-decoded address lines.
+	ORR	r1, r4, r1		; Set the non-decoded address bit in the start address.
+
+30	CMP	r10, #0			; If the workspace has not been allocated...
+	MOVEQ	r10, r1			; ... use this block.
+	MOVEQ	r4, #0			; Initialise the counter.
+
+	; The block/fragment to be added is between r1 and r1+r2.
+	LDRNE	r4, [r10]		; Get the old counter if there was one.
+	STMIA	r10!, {r1, r2}		; Store address and size.
+	ADD	r4, r4, #1		; Increment the counter.
+	STR	r4, [r10]		; Store the counter.
+
+	MOV	pc, lr			; We've done with this block now.
+
+
+ ]
+
 ; Memory map initialisation table
 ; Consists of word triplets (size,logaddr,type)
 ; where size    is size in bytes of area (size=0 terminates list)
@@ -2568,11 +2555,6 @@ TimeCPU ROUT            ;ONLY WORKS FOR IOMD(L) machines - this shouldn't be a p
         MOVEQ   pc,lr
   ]
 
-  [ STB
-        BIC     r9, r9, #3 :SHL: 8
-        STR     r9, [r9]                ; turn off refresh for a bit
-  ]
-
 ; Time CPU/Memory speed
         LDR     r1, =&7FFE              ; 32K @ 2MHz = ~16ms limit
         MOV     r3, #IOC                ; Address of the IO controller
@@ -3856,56 +3838,66 @@ L1L2PTe_WPROMdone
 
         LDR     r0,=MaxCamEntry
         LDR     r0,[r0]
-        ADD     r0,r0,#1               ; = no. of 4k RAM pages in machine
-        MOV     r0,r0,LSR #8           ; = no. of Mbytes in machine
-        ADD     r0,r0,#3
-        BIC     r0,r0,#3               ; round up to next 4 Mb
-        CMP     r0,#28                 ; if 28Mb or more, no pages to be rescued from L2PT AppSpace
+        ADD     r0,r0,#1+255+768		; = no. of 4k RAM pages in machine + 255 + 3*256
+        MOV     r0,r0,LSR #8			; = no. of Mbytes in machine rounded up + 3
+        BIC     r0,r0,#3			; round up to next 4 Mb
+        CMP     r0,#28				; if 28Mb or more, no pages to be rescued from L2PT AppSpace
         BHS     %FT09
         LDR     r1,=AppSpaceDANode
         MOV     r2,r0,LSL #20
-        STR     r2,[r1,#DANode_MaxSize] ; update AppSpace max size
-        MOV     r0,r0,LSR #2           ; no. of L2PT AppSpace pages which cannot be rescued
+        STR     r2,[r1,#DANode_MaxSize]		; update AppSpace max size
+        MOV     r0,r0,LSR #2			; no. of L2PT AppSpace pages which cannot be rescued
         MOV     r1,#L2PT
-        ADD     r1,r1,#(L2PT :SHR: 10) ;the L2PT of the L2PT (and first 7 entries are for App Space)
-        ADD     r1,r1,r0,LSL #2        ;first entry for rescue
+        ADD	r4, r1, #L1PT-L2PT
+        ADD	r4, r4, r0, LSL #4		;the L1PT entry to blank out (4 L1 entries per L2 entry)
+        ADD     r1,r1,#(L2PT :SHR: (12-2))	;the L2PT of the L2PT (and first 7 entries are for App Space)
+        ADD     r1,r1,r0,LSL #2			;first entry for rescue
         LDR     r3,=FreePoolDANode
         LDR     r2,[r3,#DANode_Base]
-        LDR     r3,[r3,#DANode_Size]
-        ADD     r2,r2,r3               ; r2 -> next logical address for a rescued page
-        MOV     r5,r3                  ; FreePool size so far
+        LDR     r5,[r3,#DANode_Size]		; FreePool size so far
+        ADD     r2,r2,r5			; r2 -> next logical address for a rescued page
 
-        SUB     sp,sp,#16              ; room for 1 page block entry + terminator
+        SUB     sp,sp,#16			; room for 1 page block entry + terminator
         MOV     r3,sp
 05
-        LDR     r4,[r1],#4             ; pick up the L2PT entry
-        BIC     r4,r4,#&0FF
-        BIC     r4,r4,#&F00            ; mask to leave physical address only
-        STR     r4,[r3,#8]             ; store physical address in word 2 of page block entry
-        Push    "r0-r2"
+        Push    "r0"
+        LDR     r0,[r1],#4			; pick up the L2PT entry
+        BIC     r0,r0,#&0FF
+        BIC     r0,r0,#&F00			; mask to leave physical address only
+        STR     r0,[r3,#8]			; store physical address in word 2 of page block entry
+
+        Push    "r1-r2"
         MOV     r0,#&0C00
         MOV     r1,r3
         MOV     r2,#1
-        SWI     XOS_Memory             ; fill in page number, given physical address
-        Pull    "r0-r2"
-        MOV     r4,#2                  ; means inaccessible in user mode (destined for FreePool)
-        STR     r4,[r3,#8]
-        MOV     r4,#-1
-        STR     r4,[r3,#12]            ; terminator
-        STR     r2,[r3,#4]             ; new logical address for page
-        Push    "r0"
+        SWI     XOS_Memory			; fill in page number, given physical address
+
+        MOV     r0,#2				; means inaccessible in user mode (destined for FreePool)
+        STR     r0,[r3,#8]
+        MOV     r0,#-1
+        STR     r0,[r3,#12]			; terminator
+        Pull    "r1-r2"
+
+        STR     r2,[r3,#4]			; new logical address for page
         MOV     r0,r3
         SWI     XOS_SetMemMapEntries
+
+	MOV	r0, #0				; Blank out the L1PT entries for the page table we just removed
+	STR	r0, [r4], #4
+	STR	r0, [r4], #4
+	STR	r0, [r4], #4
+	STR	r0, [r4], #4
+
         Pull    "r0"
         ADD     r2,r2,#4096
-        ADD     r5,r5,#4096            ; next page
+        ADD     r5,r5,#4096			; next page
         ADD     r0,r0,#1
-        CMP     r0,#7                  ;7 entries in total for full 28Mb AppSpace
+        CMP     r0,#7				;7 entries in total for full 28Mb AppSpace
         BNE     %BT05
-        ADD     sp,sp,#16              ;drop the workspace
+        ADD     sp,sp,#16			;drop the workspace
 
-        LDR     r4,=FreePoolDANode
-        STR     r5,[r4,#DANode_Size]   ;update FreePoolSize
+        LDR     r0,=FreePoolDANode
+        STR     r5,[r0,#DANode_Size]		;update FreePoolSize
 
 09
         Pull    "r0-r5,pc"
diff --git a/s/GetAll b/s/GetAll
index 773e80b1..04d4b5af 100644
--- a/s/GetAll
+++ b/s/GetAll
@@ -200,7 +200,7 @@ Module          SETL    {FALSE}
                 GBLL    IncludeTestSrc  ; whether test code is included
                 ! 0, "Modified code"
  [ MorrisSupport
-IncludeTestSrc  SETL    {FALSE}
+IncludeTestSrc  SETL    {TRUE}
  |
 IncludeTestSrc  SETL    :LNOT: (MEMM_Type = "MEMC2") ; not on internal test versions
  ]
@@ -621,6 +621,7 @@ largest_rma_size    * (128*1024)                 ; and the ceiling for rma use
         GET     Hdr:Wimp
         GET     Hdr:ColourTran
         GET     Hdr:Debug
+        GET	Hdr:nvram
         GET     s.PMF.DEF          ; Common with 6502 code in the keyboard
         Protocol
 
diff --git a/s/Middle b/s/Middle
index 4085e005..0d3c8254 100644
--- a/s/Middle
+++ b/s/Middle
@@ -1313,36 +1313,65 @@ GetMachineAddressCMOS
 ;       r1 = upper 2 bytes (or 0)
 ;       EQ => valid, NE => invalid
 ;
-        Push    "r2-r5,lr"
-        MOV     r1, #EtherAddrCMOS
-        MOV     r2, #0                                  ; For lower 4 bytes
-        MOV     r3, #0                                  ; For upper 2 bytes
-        MOV     r4, #0                                  ; For checksum
-        MOV     r5, #6                                  ; Read 6 bytes
-01
-        MOV     r0, r1
-        BL      Read
-        ADD     r1, r1, #1                              ; Move on to next byte
-        MOV     lr, r2, LSR #24                         ; Get top byte of lower word
-        ORR     r3, lr, r3, LSL #8                      ; and put it into bottom byte of upper word
-        ORR     r2, r0, r2, LSL #8                      ; Put byte read into bottom byte of upper word
-        ADD     r4, r4, r0                              ; Add byte to checksum
-        SUBS    r5, r5, #1                              ; Any more bytes?
-        BNE     %BT01
+	Entry	"r2,r3", 8				; Preserve these
+
+	ADR	r0, NVRAM_TAG_MACAddress		; Read the MAC address
+	MOV	r1, sp
+	MOV	r2, #6
+	SWI	XNVRAM_Read
+	MOVVS	r0, #&ffffffff
+	TST	r0, #&80000000				; Check for errors
+	BNE	%FT10
+
+	ADR	r0, NVRAM_TAG_MACAddressChecksum	; Read the checksum
+	ADD	r1, sp, #6
+	MOV	r2, #1
+	SWI	NVRAM_Read
+	MOVVS	r0, #&ffffffff
+	TST	r0, #&80000000				; Check for errors
+10
+	MOV	r0, #0
+	MOV	r1, #0
+	BNE	%FT20					; Return zero on error
 
-        ASSERT  EtherCheckCMOS = EtherAddrCMOS+6
-        MOV     r0, r1                                  ; Read checksum byte
-        BL      Read
-        AND     r4, r4, #&FF                            ; Bottom byte of checksum
-        EOR     r0, r0, #&FF                            ; should be inverted in CMOS
-        TEQ     r0, r4
-        MOVEQ   r0, r2                                  ; Use CMOS values if valid
-        MOVEQ   r1, r3
-        MOVNE   r0, #0                                  ; otherwise no address.
-        MOVNE   r1, #0
-        Pull    "r2-r5,pc"
-        ]
+	LDRB	r3, [sp, #0]				; Get the first byte into checksum
+	MOV	r1, r3, ASL #8				; Store into result
+
+	LDRB	r2, [sp, #1]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r1, r1, r2, ASL #0			; Store into the result
+
+	LDRB	r2, [sp, #2]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	MOV	r0, r2, ASL #24				; Store into the result
 
+	LDRB	r2, [sp, #3]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r0, r0, r2, ASL #16			; Store into the result
+
+	LDRB	r2, [sp, #4]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r0, r0, r2, ASL #8			; Store into the result
+
+	LDRB	r2, [sp, #5]				; Get the next byte
+	ADD	r3, r3, r2				; Add to the checksum
+	ORR	r0, r0, r2, ASL #0			; Store into the result
+
+	LDRB	r2, [sp, #6]				; Get the checksum
+	AND	r3, r3, #&FF
+	EOR	r3, r3, #&FF
+	TEQ	r2, r3					; Check against the computed value
+	MOVNE	r0, #0					; Zero the MAC address on failure
+	MOVNE	r1, #0
+
+20
+	EXITS
+
+NVRAM_TAG_MACAddress
+	= "MACAddress", 0
+NVRAM_TAG_MACAddressChecksum
+	= "MACAddressChecksum", 0
+        ]
 
 ; OS_ReadSysInfo 5
 ;
diff --git a/s/NewReset b/s/NewReset
index 9215d731..2c6b71e1 100644
--- a/s/NewReset
+++ b/s/NewReset
@@ -968,7 +968,7 @@ reset_loop
 
 	MOV	R0, #VduCMOS
 	BL	Read
- [ IOMD_C_MonitorType = 0 :LAND: MPEGPoduleNTSCNotPALMask = 0
+ [ IOMD_C_MonitorType = 0 :LAND: MPEGPoduleNTSCNotPALMask = 0 :LAND: IOMD_C_PALNTSCType = 0
 ; Force TV if we don't have a MonitorType auto-detect bit
 	TEQ	R0, #(Sync_Separate :OR: MonitorType0)
  |
@@ -1232,7 +1232,7 @@ DefaultCMOSTable ; list of non-zero options wanted :
         =       DBTBCMOS,	        (1:SHL:4)				; Boot
         =       YearCMOS,               97
         =       YearCMOS+1,             19
-  [ IOMD_C_MonitorType = 0
+  [ IOMD_C_MonitorType = 0 :LAND: MPEGPoduleNTSCNotPALMask = 0 :LAND: IOMD_C_PALNTSCType = 0
 ; TV if we don't have a MonitorType auto-detect bit
 	=	VduCMOS,	        Sync_Separate :OR: MonitorType0
   |
diff --git a/s/PMF/osinit b/s/PMF/osinit
index a93658ad..8714c95f 100644
--- a/s/PMF/osinit
+++ b/s/PMF/osinit
@@ -20,7 +20,7 @@ ErrorsInR0 SETL Module                  ; if FALSE, use XOS_GenerateError for
                                         ; if TRUE, return error ptr in R0
 
         GBLL    ProtectStationID        ; if TRUE, disallow OSBYTE &A2,0,n
-ProtectStationID SETL {TRUE}
+ProtectStationID SETL {TRUE}:LAND::LNOT:STB
 
 ; *****************************************************************************
 
-- 
GitLab