From 5f4a35164c399305b42851e4b30bbb2e62723da7 Mon Sep 17 00:00:00 2001
From: Robert Catherall <rcathera@gitlab.riscosopen.org>
Date: Mon, 4 Sep 2000 18:47:59 +0000
Subject: [PATCH] Added 32K EEPROM support.

  New routine in i2cutils that allows access to protected sections such as
  MAC address
  OS_ReadSysInfo 4 now checks both copies MACAddress if MACNVRAM2copies is set
Detail:
  32K EEPROM has to be configured with IIC address &A6 (i.e wired up on the pcb)
  ClockNVMemoryFast has been replaced with MaxI2Cspeed so that several different
  rates can be used depending on the devices on the IIC bus.
Admin:
  Need to implement routine that can use one copy of the MAC address to
  replace the other in the event of it being corrupted.


Version 5.33. Tagged as 'Kernel-5_33'
---
 VersionASM     |  12 ++--
 VersionNum     |  18 +++---
 s/Middle       | 164 +++++++++++++++++++++++++++++++++++++++++++------
 s/PMF/i2cutils |  63 +++++++++++++------
 4 files changed, 202 insertions(+), 55 deletions(-)

diff --git a/VersionASM b/VersionASM
index 602c97e3..7e755985 100644
--- a/VersionASM
+++ b/VersionASM
@@ -8,11 +8,11 @@
                         GBLS    Module_FullVersion
                         GBLS    Module_ApplicationDate2
                         GBLS    Module_ApplicationDate4
-Module_MajorVersion     SETS    "5.32"
-Module_Version          SETA    532
+Module_MajorVersion     SETS    "5.33"
+Module_Version          SETA    533
 Module_MinorVersion     SETS    ""
-Module_Date             SETS    "18 Aug 2000"
-Module_ApplicationDate2 SETS    "18-Aug-00"
-Module_ApplicationDate4 SETS    "18-Aug-2000"
-Module_FullVersion      SETS    "5.32"
+Module_Date             SETS    "04 Sep 2000"
+Module_ApplicationDate2 SETS    "04-Sep-00"
+Module_ApplicationDate4 SETS    "04-Sep-2000"
+Module_FullVersion      SETS    "5.33"
                         END
diff --git a/VersionNum b/VersionNum
index a6ef902e..385d7c42 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,18 +1,18 @@
-/* (5.32)
+/* (5.33)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG        5.32
+#define Module_MajorVersion_CMHG        5.33
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                18 Aug 2000
+#define Module_Date_CMHG                04 Sep 2000
 
-#define Module_MajorVersion             "5.32"
-#define Module_Version                  532
+#define Module_MajorVersion             "5.33"
+#define Module_Version                  533
 #define Module_MinorVersion             ""
-#define Module_Date                     "18 Aug 2000"
+#define Module_Date                     "04 Sep 2000"
 
-#define Module_ApplicationDate2         "18-Aug-00"
-#define Module_ApplicationDate4         "18-Aug-2000"
+#define Module_ApplicationDate2         "04-Sep-00"
+#define Module_ApplicationDate4         "04-Sep-2000"
 
-#define Module_FullVersion              "5.32"
+#define Module_FullVersion              "5.33"
diff --git a/s/Middle b/s/Middle
index 166b1170..1ae8e459 100644
--- a/s/Middle
+++ b/s/Middle
@@ -1305,13 +1305,11 @@ IOST_BATMAN     * 64    ;Stork keyboard/battery controller seems to be present
         ORRNE   r2, r2, #&00000100              ;NE, Morris based machine with IOMDL
         ORRNE   r2, r2, #&00010000              ;NE, and VIDC2L
  ]
- [ ClockNVMemoryFast
         MOV     r1, #0
         LDRB    r1, [r1, #NVRamSpeed]
         SUB     r1, r1, #1                      ; catch zero = slow (just in case)
         CMP     r1, #3-1                        ; speed is 3 for 400kHz, 10 for 100kHz.
         ORRLS   r2, r2, #&01000000              ; indicate fast speed
- ]
  [ StopClocksDuringIdle
         ORR     r2, r2, #&02000000
  ]
@@ -1441,32 +1439,159 @@ ExitNoEthernetAddress
         ExitSWIHandler
         ]
 
-        [ STB
+ [ STB
+
+NVRAM_TAG_MACAddress
+	= "MACAddress", 0
+NVRAM_TAG_MACAddressChecksum
+	= "MACAddressChecksum", 0
+NVRAM_TAG_MACAddress2nd
+        = "MACAddress2nd", 0
+NVRAM_TAG_MACAddressChecksum2nd
+        = "MACAddressChecksum2nd", 0
+
+        ALIGN
+
 GetMachineAddressCMOS
 ; Out:  r0 = lower 4 bytes (or 0)
 ;       r1 = upper 2 bytes (or 0)
 ;       EQ => valid, NE => invalid
 ;
-	Entry	"r2,r3", 8				; Preserve these
+        Entry   "r2-r5", 8                              ; Preserve these + get 8 bytes workspace
+
+        ADR     r0,NVRAM_TAG_MACAddress
+        ADR     r3,NVRAM_TAG_MACAddressChecksum
+        BL      CheckOneCopyOfMachineAddressCMOS        ; Get 1st copy of MAC in r0=low 4 bytes,
+                                                        ; r1=upper 2 bytes of MAC in bytes 0,1  stored checksum in byte 2,  calculated checksum in byte 3
+ [ MACNVRAM2copies
+        MOV     r4,r0
+        MOV     r5,r1
+
+        ADR     r0,NVRAM_TAG_MACAddress2nd
+        ADR     r3,NVRAM_TAG_MACAddressChecksum2nd
+        BL      CheckOneCopyOfMachineAddressCMOS        ; Get 2nd copy of MAC
+
+        CMP     r0,r4
+        CMPEQ   r1,r5
+        BNE     %FT41                                   ; Have different values - i.e one (possibly both) is wrong/broken
+ ] ;two copies of MAC
+
+        MOV     r2,r1,LSR#16                            ; move checksum values into low bytes
+        AND     r3,r2,#&ff                              ; r3=stored checksum
+        MOV     r2,r2,LSR#8                             ; r2=calculated checksum
+        CMP     r2,r3                                   ; do the checksums match
+        BNE     %FT43                                   ; if not then we have unrecoverable fault, both values identical but checksums broken
+                                                        ; this would be the case for an unprogrammed CMOS
+        MOV     r2,#&ff
+        ORR     r2,r2,r2,LSL#8                          ; mask for removing checksums
+        AND     r1,r1,r2                                ; #&0000ffff remove checksums from r1
+        EXIT                                            ; return with valid MAC in r0,r1 and flags set to EQ by branch just above
+
+ [ MACNVRAM2copies
+;two copies differ
+41
+        MOV     r2,r5,LSR#16                            ; move checksum for 1st copy into low bytes
+        AND     r3,r2,#&ff                              ; r3=stored checksum
+        MOV     r2,r2,LSR#8                             ; r2=calculated checksum
+        CMP     r2,r3                                   ; do the checksums match
+        BEQ     %FT45                                   ; okay need to repair second set
+
+        MOV     r2,r1,LSR#16                            ; move checksum for 2nd copy into low bytes
+        AND     r3,r2,#&ff                              ; r3=stored checksum
+        MOV     r2,r2,LSR#8                             ; r2=calculated checksum
+        CMP     r2,r3                                   ; do the checksums match
+        BEQ     %FT46                                   ; okay need to repair first set
+ ]
+;we arrive here if we have a situation from which no sensible MAC can be derived
+;i) both values are broken
+43
+        MOV     r0,#0
+        MOV     r1,#0
+        EXIT                                            ;return with r0,r1 both zero to indicate no valid address, two possible paths here both have NE flags
+ [ MACNVRAM2copies
+;checksum is valid for first set so repair second set
+45
+        ADR     r3,NVRAM_TAG_MACAddress2nd
+        ADR     r0,NVRAM_TAG_MACAddressChecksum2nd
+        B       %FT47
+
+;checksum is valid for second set so repair first set
+46
+        MOV     r4,r0                                   ;get values of 2nd set into write registers
+        MOV     r5,r1
+        ADR     r3,NVRAM_TAG_MACAddress
+        ADR     r0,NVRAM_TAG_MACAddressChecksum
+
+;store MAC (+ check sum) in r4,r5, and checksum in r2 to NVRAM tags given by r0 and r3
+47
+ [ 1=2
+        ; forgot that NVRAM_Write will fail
+        ; on locked locations such as .. the MAC addresses...
+        ; this will be modified shortly to call a new SWI provided
+        ; by the NVRAM module to turn a tag into an address and
+        ; then perform the write using routines in the i2cutils
+        ; section of the kernel.
+
+        MOV     r1, sp                                  ;some workspace
+        STRB    r2, [r1,#0]                             ;store the checksum
+        MOV     r2, #1
+        SWI     XNVRAM_Write
+        ;TST     r0, #&80000000                          ; Check for errors
+        ;BNE     %FT48                                   ; Oh dear
+
+        BIC     r5,r5,#&ffff0000                        ;get rid of checksum - we already have a value in r2 extracted earlier
+        MOV     r0,r3                                   ;NVRAM_TAG_MACAddress
+        MOV     r1,sp                                   ;workspace
+
+        MOV     r3,r5
+        STRB    r3,[r1,#1]
+        MOV     r3,r3,LSR#8
+        STRB    r3,[r1,#0]
+        MOV     r3,r4
+        STRB    r3,[r1,#5]
+        MOV     r3,r3,LSR#8
+        STRB    r3,[r1,#4]
+        MOV     r3,r3,LSR#8
+        STRB    r3,[r1,#3]
+        MOV     r3,r3,LSR#8
+        STRB    r3,[r1,#2]
+
+        MOV     r2,#6
+        SWI     XNVRAM_Write
+        ;TST     r0, #&80000000                          ; Check for errors
+        ;BNE     %FT48                                   ; Oh dear
+ ]
+;return with the values from r4,r5 in r0,r1 and flags eq
+;48
+        MOV     r0,r4
+        MOV     r1,r5
+        CMP     r1,r1                                   ;make flags equal - is this required?
+        EXIT
+
+ ] ; MACNVRAM2copies
+
+;On entry r0 points to MAC address Tag name
+;         r3 points to Checksum Tag name
+CheckOneCopyOfMachineAddressCMOS
+        Entry   ,8
 
-	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
+        BNE     MachineAddressNVRAMError
 
-	ADR	r0, NVRAM_TAG_MACAddressChecksum	; Read the checksum
+        MOV     r0, r3
 	ADD	r1, sp, #6
 	MOV	r2, #1
-	SWI	NVRAM_Read
+        SWI     XNVRAM_Read
 	MOVVS	r0, #&ffffffff
 	TST	r0, #&80000000				; Check for errors
-10
+        BNE     MachineAddressNVRAMError
+
 	MOV	r0, #0
 	MOV	r1, #0
-	BNE	%FT20					; Return zero on error
 
 	LDRB	r3, [sp, #0]				; Get the first byte into checksum
 	MOV	r1, r3, ASL #8				; Store into result
@@ -1494,18 +1619,17 @@ GetMachineAddressCMOS
 	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
+        ORR     r1,r1,r2,LSL#16                            ;put stored checksum in byte 2
+        ORR     r1,r1,r3,LSL#24                            ;put calculated checksum in byte 3
+49
+        EXIT
 
-20
-	EXIT
+MachineAddressNVRAMError
+        MOV     r0,#0
+        MOV     r1,#0
+        EXIT
 
-NVRAM_TAG_MACAddress
-	= "MACAddress", 0
-NVRAM_TAG_MACAddressChecksum
-	= "MACAddressChecksum", 0
-        ]
+ ]
 
 ; OS_ReadSysInfo 5
 ;
diff --git a/s/PMF/i2cutils b/s/PMF/i2cutils
index 6f3152ab..008479f9 100644
--- a/s/PMF/i2cutils
+++ b/s/PMF/i2cutils
@@ -51,6 +51,19 @@ E2ROMAddress2K_OTP	*	&60     ; 24C174 device - OTP section
 E2ROMAddress4K          *       &a4     ; 24C32 device - 4K (top 1K protectable)
 E2ROMAddress8K          *       &a2     ; 24C64 device - 8K (top 2K protectable)
 E2ROMAddress16K         *       &a8     ; 24C128 device - 16K
+E2ROMAddress32K         *       &a6     ; 24CS256 device - 32K (top 2K possibly OTP)
+  ]
+
+; Choose a lower limit on the number of ticks per clock phase based on the
+; MaxI2Cspeed variable defined in Hdr:Machine.<Machine>
+  [ MaxI2Cspeed >= 1000
+I2Cticks        *       1
+  |
+  [ MaxI2Cspeed >= 400
+I2Cticks        *       3
+  |
+I2Cticks        *       10
+  ]
   ]
 
 ; *****************************************************************************
@@ -118,7 +131,6 @@ SetC1C0 ROUT
 	MOV	R2, #IOC
 	STRB	R0, [R2, #IOCControl]
 
- [ ClockNVMemoryFast
         [ :LNOT: :DEF: TestHarness
         MOV	R0, #0
         LDRB	R0, [R0, #NVRamSpeed]
@@ -127,9 +139,6 @@ SetC1C0 ROUT
         ]
         TEQ     R0, #0
         MOVEQ   R0, #10                         ; default value if speed not checked yet
- |
-        MOV     R0, #10                         ; 5µs delay
- ]
 	BL	DoMicroDelay
 
  [ No26bitCode
@@ -245,7 +254,7 @@ Start	ROUT
 	MOV	R1, #1
 	BL	SetC1C0
 
- [ :LNOT: ClockNVMemoryFast
+ [ I2Cticks >= 10
 ; Hold start condition for BMU
 
 	MOV	R2, #IOC
@@ -525,6 +534,17 @@ WriteWithError ROUT
 
         MakeErrorBlock CoreNotWriteable
 
+WriteWithoutProtection                  ; allowing write to "OTP" and protected section
+        Push    "R0-R4, R14"
+        BL      MangleCMOSAddress
+        Pull    "R0-R4, PC", CS         ; if invalid, then exit
+        MOV     R2, R0
+        MOV     R3, R1
+        CMP     R0, #&10
+        MOVLO   R4, #&1000000           ; don't change checksum for OTP
+        BLO     %FT10
+        B       %FT08                   ; do change checksum for protected region
+
 Write
 	Push	"R0-R4, R14"
 	BL	MangleCMOSAddress
@@ -544,6 +564,7 @@ Write
 
 	MOV	R2, R0
 	MOV	R3, R1
+08
  [ ChecksumCMOS
 	BL	ReadStraight		; calculate new checksum :
 	MOV	R4, R0
@@ -1615,14 +1636,12 @@ InitCMOSCache	ENTRY "r0-r6"
 ; Need to set the slowest speed so we can probe
 
         MOV     R2, #0
-      [ ClockNVMemoryFast
         MOV     R3, #10         ; Default speed setting (5µs delays)
 	[ :LNOT: :DEF: TestHarness
         STRB    R3, [R2, #NVRamSpeed]
 	|
         STRB    R3, NVSpeed
 	]
-      ]
 
 ;	First determine what hardware we've got fitted, R4 holds the number of
 ;	256 byte blocks that we've found
@@ -1637,6 +1656,7 @@ InitCMOSCache	ENTRY "r0-r6"
 	|
 	STRB	R4, RTCFlag
 	]
+        MOV     R3, #10         ; assume 100kHz to start with
         MOV     R5, #4          ; assume 16 byte page size to start with
         MOV     R6, #0          ; assume not protected
 
@@ -1645,9 +1665,7 @@ InitCMOSCache	ENTRY "r0-r6"
 	MOV	r0, #(E2ROMAddress2K+14)
 	BL	DummyAccess
 	MOVVC	R4, #8
-      [ ClockNVMemoryFast
         MOVVC   R3, #3          ; Fast speed setting (1.5µs delays)
-      ]
 	BVC	%FT5
 
 ; Have we got a 1K E² ?
@@ -1672,9 +1690,7 @@ InitCMOSCache	ENTRY "r0-r6"
 	BL	DummyAccess
 	MOVVC	R4, #64
         MOVVC   R5, #6          ; 64 byte page size
-      [ ClockNVMemoryFast
         MOVVC   R3, #3          ; Fast speed setting (1.5µs delays)
-      ]
         BVC     %FT5
 
 ; Have we got a 4K device?
@@ -1685,9 +1701,7 @@ InitCMOSCache	ENTRY "r0-r6"
 	MOVVC	R4, #16
         MOVVC   R6, #12         ; Only bottom 3K writable
         MOVVC   R5, #5          ; 32 byte page size
-      [ ClockNVMemoryFast
         MOVVC   R3, #3          ; Fast speed setting (1.5µs delays)
-      ]
         BVC     %FT5
 
 ; Have we got an 8K device?
@@ -1698,11 +1712,20 @@ InitCMOSCache	ENTRY "r0-r6"
 	MOVVC	R4, #32
         MOVVC   R6, #24         ; Only bottom 6K writable
         MOVVC   R5, #5          ; 32 byte page size
-      [ ClockNVMemoryFast
         MOVVC   R3, #3          ; Fast speed setting (1.5µs delays)
-      ]
+        BVC     %FT5
+
+; Have we got a 32K device?
 
-	MOVVS   R1, #RTCAddress
+        MOV     r1, #E2ROMAddress32K
+        MOV     r0, #E2ROMAddress32K
+        BL      DummyAccess
+        MOVVC   R4, #128        ; 128,120,6,1
+        MOVVC   R6, #120        ; Only bottom 30K writable
+        MOVVC   R5, #6          ; 64 byte page size
+        MOVVC   R3, #1          ; Hyper-fast speed setting (0.5µs delays - 1MHz part)
+
+        MOVVS   R1, #RTCAddress
         MOVVS   R5, #8          ; 256 byte page size for CMOS
 
 5
@@ -1714,17 +1737,17 @@ InitCMOSCache	ENTRY "r0-r6"
         TEQ     R6, #0
         MOVEQ   R6, R4
         STRB    R6, [R2, #NVRamWriteSize]
-      [ ClockNVMemoryFast
+
+        CMP     R3, #I2Cticks   ; clamp speed to maximum bus speed
+        MOVLO   R3, #I2Cticks
         STRB    R3, [R2, #NVRamSpeed]
-      ]
+
 	LDR	R3, =CMOSRAMCache
 	|
 	STRB    R1, NVBase
 	STRB	R4, NVSize
         STRB    R5, NVPageSize
-      [ ClockNVMemoryFast
         STRB    R3, NVSpeed
-      ]
 	ADR	R3, i2cWorkSpace
 	]
 
-- 
GitLab