i2cutils 52.1 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.PMF.i2cutils

; Authors JBiggs (m2), PFellows, TDobson, AGodwin

Neil Turton's avatar
Neil Turton committed
19 20 21 22 23 24 25 26 27 28 29 30 31
; ***********************************
; ***    C h a n g e   L i s t    ***
; ***********************************

; Date       Name  Description
; ----       ----  -----------
; 28-Mar-95  JRH   Added support for E2ROMs and/or CMOS, conditioned on
;                  E2ROMSupport which is defined elsewhere
;                  Uses RTCFitted and NVRamSize in KernelWS
; 03-Jul-96  JRH   Took out code conditioned on :LNOT: NewClockChip
;                  Fixed support for E2ROM. E2 works in the same gross way as
;                  CMOS. Any E2 fitted > 256 bytes will not be accessed by these
;                  routines.
Kevin Bracey's avatar
Kevin Bracey committed
32 33
; 07-Dec-96  AMG   Renaissance. Leave this file as is, allowing the E2ROMSupport
;                  switch to disable non-STB bits
Kevin Bracey's avatar
Kevin Bracey committed
34 35 36
; 12-Jun-97  TMD   (Really) fix OTP access problem.
; 17-Sep-98  KJB   Add support for 16K 24C128 EEPROM.
; 21-Sep-98  KJB   Add OS_NVMemory SWI.
37
; 30-Jul-99  KJB   Add support for 8K 24C64 EEPROM.
38
; 23-Sep-99  KJB   Remove support for 24C64, add support for 4K and 8K protectable ATMEL parts.
Neil Turton's avatar
Neil Turton committed
39

Kevin Bracey's avatar
Kevin Bracey committed
40
PhysChecksum		*	(((CheckSumCMOS + &30) :MOD: &F0) + &10)
Neil Turton's avatar
Neil Turton committed
41 42

; Device addresses
Kevin Bracey's avatar
Kevin Bracey committed
43 44
RTCAddressPHI		*	&a0     ; Philips RTC + 240 byte CMOS
RTCAddressDAL		*	&d0     ; Dallas RTC + 56 byte CMOS
Kevin Bracey's avatar
Kevin Bracey committed
45 46
E2ROMAddress2K		*	&e0     ; 24C174 device - 2K
E2ROMAddress2K_OTP	*	&60     ; 24C174 device - OTP section
Kevin Bracey's avatar
Kevin Bracey committed
47 48 49 50 51
E2ROMAddress4K		*	&a4     ; 24C32 device - 4K (top 1K protectable)
E2ROMAddress8K_prot	*	&a2     ; 24C64 device - 8K (top 2K protectable)
E2ROMAddress8K		*	&ae     ; 24C64 device - 8K
E2ROMAddress16K		*	&a8     ; 24C128 device - 16K
E2ROMAddress32K		*	&a6     ; 24CS256 device - 32K (top 2K possibly OTP)
Robert Catherall's avatar
Robert Catherall committed
52

Dan Ellis's avatar
Dan Ellis committed
53

Neil Turton's avatar
Neil Turton committed
54 55
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
56
;	HexToBCD - Convert byte in hex to BCD
Neil Turton's avatar
Neil Turton committed
57
;
Neil Turton's avatar
Neil Turton committed
58
; in:	R0 = byte in hex
Neil Turton's avatar
Neil Turton committed
59
;
Neil Turton's avatar
Neil Turton committed
60 61
; out:	R0 = byte in BCD (ie R0 := (R0 DIV 10)*16 + R0 MOD 10)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
62 63 64
;

HexToBCD ROUT
Neil Turton's avatar
Neil Turton committed
65 66 67 68 69
	Push	"R1,R2, R14"
	MOV	R1, #10
	DivRem	R2, R0, R1, R14			; R2=R0 DIV 10; R0=R0 MOD 10
	ADD	R0, R0, R2, LSL #4
	Pull	"R1,R2, PC"
Neil Turton's avatar
Neil Turton committed
70 71 72

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
73
;	BCDToHex - Convert byte in BCD to hex
Neil Turton's avatar
Neil Turton committed
74
;
Neil Turton's avatar
Neil Turton committed
75
; in:	R0 = byte in BCD (ie x*16 + y)
Neil Turton's avatar
Neil Turton committed
76
;
Neil Turton's avatar
Neil Turton committed
77 78
; out:	R0 = byte in hex (ie x*10 + y)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
79 80 81
;

BCDToHex ROUT
Neil Turton's avatar
Neil Turton committed
82 83 84 85 86
	Push	"R14"
	MOV	R14, R0, LSR #4			; R14 := x
	ADD	R14, R14, R14, LSL #1		; R14 := x*3
	SUB	R0, R0, R14, LSL #1		; R0 := R0 - x*6 = x*10
	Pull	"PC"
Neil Turton's avatar
Neil Turton committed
87

88 89

; *****************************************************************************
Kevin Bracey's avatar
Kevin Bracey committed
90 91 92
;
;       HTBSR9 - hex to BCD and store at "next free byte" R9
;
93
HTBS9   ROUT
94
        Push    R14
95 96 97
        BL      HexToBCD
        STRB    R0, [R9], #1
        Pull    PC
Neil Turton's avatar
Neil Turton committed
98 99 100

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
101
;	Write - Write a byte of CMOS RAM specified by logical address
Neil Turton's avatar
Neil Turton committed
102
;
Neil Turton's avatar
Neil Turton committed
103 104
; in:	R0 = address in CMOS RAM
;	R1 = data
Neil Turton's avatar
Neil Turton committed
105
;
Neil Turton's avatar
Neil Turton committed
106
; out:	All registers preserved
Neil Turton's avatar
Neil Turton committed
107 108
;

Kevin Bracey's avatar
Kevin Bracey committed
109 110 111 112 113 114 115 116 117
WriteWithError ROUT
        Push    "R0-R4, R14"
        BL      MangleCMOSAddress
        BCC     %FT05

        ADD     R13, R13, #4            ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotWriteable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
118 119
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
120
 ]
Kevin Bracey's avatar
Kevin Bracey committed
121
        Pull    "R1-R4,PC"
Kevin Bracey's avatar
Kevin Bracey committed
122 123 124

        MakeErrorBlock CoreNotWriteable

Robert Catherall's avatar
Robert Catherall committed
125 126 127 128 129 130 131 132 133 134 135
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

Kevin Bracey's avatar
Kevin Bracey committed
136
Write
Neil Turton's avatar
Neil Turton committed
137 138 139
	Push	"R0-R4, R14"
	BL	MangleCMOSAddress
	Pull	"R0-R4, PC", CS		; if invalid, then exit
Kevin Bracey's avatar
Kevin Bracey committed
140 141 142 143 144
05
  [ E2ROMSupport
        CMP     r0, #&10
        Pull    "R0-R4, PC", CC         ; don't write to OTP section
  ]
Neil Turton's avatar
Neil Turton committed
145

Stewart Brodie's avatar
Stewart Brodie committed
146
  [ E2ROMSupport
147 148
        MOV     R14, #0                 ; don't write to protected section
        LDRB    R14, [R14, #NVRamWriteSize]
149
        CMP     R0, R14, LSL #8         ; (note assumption that NVRamWriteSize is
150
        Pull    "R0-R4, PC", HS         ; outside mangled region).
Stewart Brodie's avatar
Stewart Brodie committed
151
  ]
152

Neil Turton's avatar
Neil Turton committed
153 154
	MOV	R2, R0
	MOV	R3, R1
Robert Catherall's avatar
Robert Catherall committed
155
08
Neil Turton's avatar
Neil Turton committed
156 157 158
 [ ChecksumCMOS
	BL	ReadStraight		; calculate new checksum :
	MOV	R4, R0
159 160 161
        TEQ     R4, R3                  ; don't bother with write if
        Pull    "R0-R4, PC", EQ         ; oldcontents == newcontents

Neil Turton's avatar
Neil Turton committed
162 163 164 165
	MOV	R0, #PhysChecksum
	BL	ReadStraight
	SUB	R0, R0, R4		; = oldsum - oldcontents
	ADD	R4, R0, R3		;          + newcontents
Neil Turton's avatar
Neil Turton committed
166

Neil Turton's avatar
Neil Turton committed
167 168 169 170
	AND	R4, R4, #&FF
	CMPS	R2, #PhysChecksum	; don't write new checksum ...
	ORREQ	R4, R4, #&1000000	; if checksum is being written
 ]
Neil Turton's avatar
Neil Turton committed
171
10
Kevin Bracey's avatar
Kevin Bracey committed
172 173 174
	CMP	r2, #&100		; check small cache limit
	BCS	%FT15
	LDR	R1, =CMOSRAMCache	; update cache, but always write to
Neil Turton's avatar
Neil Turton committed
175
	STRB	R3, [R1, R2]		; real hardware as well
Kevin Bracey's avatar
Kevin Bracey committed
176
15
Dan Ellis's avatar
Dan Ellis committed
177 178

  [ HAL
179
    	Push	"R2,R3,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
180 181 182 183 184 185
    	AddressHAL
    	CallHAL	HAL_NVMemoryType
    	AND 	R0, R0, #NVMemoryFlag_Provision
    	TEQ 	R0, #NVMemoryFlag_None

    	; If there's no NVmemory, all we have is the internal cache.
186
    	Pull 	"R2,R3,sb,R12", EQ
Dan Ellis's avatar
Dan Ellis committed
187 188 189 190 191 192
	Pull	"R0-R4,PC", EQ

    	TEQ 	R0, #NVMemoryFlag_HAL
    	BNE 	%FT20	    	    	; Go and do IIC stuff.

    	; Make the HAL call - we have to write the data into a buffer.
193
        Pull    "R0"
194
        STRB    R3, [sp, #-4]!
195 196 197
    	MOV 	R1, sp
    	MOV 	R2, #1
    	CallHAL	HAL_NVMemoryWrite
198 199 200 201 202
        TST     R4, #&1000000
        BNE     %FT18
        LDR     R1, =CMOSRAMCache
        STRB    R4, [R1, #PhysChecksum]
        STRB    R4, [sp]
203
        MOV     R0, #PhysChecksum
Dan Ellis's avatar
Dan Ellis committed
204 205 206
    	MOV 	R1, sp
    	MOV 	R2, #1
    	CallHAL	HAL_NVMemoryWrite
207 208 209
18
    	ADD     sp, sp, #4
    	Pull	"R3,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
210 211
    	Pull	"R0-R4,PC"
20
212
        Pull    "R2,R3,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
213 214 215
  ]


Neil Turton's avatar
Neil Turton committed
216 217 218 219 220
 [ E2ROMSupport
	MOV	R0, R2
	BL	GetI2CAddress		; convert to device address + offset
	MOV	R2, R0			; save the offset
 |
Kevin Bracey's avatar
Kevin Bracey committed
221
	MOV	R1, #RTCAddressPHI
Neil Turton's avatar
Neil Turton committed
222 223 224
 ]


225 226 227 228 229 230 231 232 233 234 235 236 237
        AND     R0, R1, #&FF            ; device address for write
        ORR     R0, R0, #1:SHL:29       ; retry
        TST     R1, #&100               ; NE if two byte offset
        SUB     R13, R13, #4
        MOV     R14, R13
        MOVNE   R1, R2, LSR #8
        STRNEB  R1, [R14], #1           ; offset (MSB)
        STRB    R2, [R14], #1           ; offset (LSB)
        STRB    R3, [R14], #1           ; data
        MOV     R1, R13
        SUB     R2, R14, R13
        BL      IIC_Op
        ADD     R13, R13, #4
Neil Turton's avatar
Neil Turton committed
238

Neil Turton's avatar
Neil Turton committed
239 240 241 242 243 244 245 246
	[ ChecksumCMOS
	TST	R4, #&1000000		; loop again to write new checksum
	MOV	R3, R4
	MOV	R2, #PhysChecksum
	ORR	R4, R4, #&1000000	; but ensure it only happens once
	BEQ	%BT10
	]
	Pull	"R0-R4, PC"
Neil Turton's avatar
Neil Turton committed
247

Kevin Bracey's avatar
Kevin Bracey committed
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
; *****************************************************************************
;
;       WriteBlock - Write a block of CMOS RAM specified by logical address
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy from
;       R2 = length
;
; out:  All registers preserved
;


WriteBlock ROUT
        Push    "R0-R4,R14"
  [     E2ROMSupport
        MOV	R14, #0
264
        LDRB    R4, [R14, #NVRamWriteSize]
Kevin Bracey's avatar
Kevin Bracey committed
265
        LDRB	R14, [R14, #NVRamSize]
266
        MOV     R4, R4, LSL #8
Kevin Bracey's avatar
Kevin Bracey committed
267 268 269
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
270
        MOV     R4, R14
Kevin Bracey's avatar
Kevin Bracey committed
271 272 273 274 275 276 277 278 279 280
  ]

        CMP     R0, R14
        BHS     %FT90

        ADDS    R3, R0, R2              ; R3 = end address - check unsigned overflow
        BCS     %FT90
        CMP     R3, R14
        BHI     %FT90

281 282 283 284 285 286
        CMP     R0, R4                  ; ignore writes totally outside writable area
        BHS     %FT80

        SUBS    R14, R3, R4
        SUBGT   R2, R2, R14             ; truncate writes partially outside writable area

Kevin Bracey's avatar
Kevin Bracey committed
287 288 289 290 291 292
        TEQ     R2, #0
        BEQ     %FT80

        CMP     R0, #CheckSumCMOS       ; are we going to write the checksum byte?
        BHI     %FT03
        CMP     R3, #CheckSumCMOS
293
        BHI     %FT05
Kevin Bracey's avatar
Kevin Bracey committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328

03
; we're not writing the checksum byte manually, so we need to update it
        MOV     R4, R1
        MOV     R1, #0
        BL      ChecksumBlock           ; find the checksum of what we're about to
        ORR     R3, R1, #&80000000      ; overwrite
        MOV     R1, R4
        B       %FT08

05      MOV     R3, #0
08      MOV     R4, #0
10      BL      WriteSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10

        TST     R3, #&80000000          ; were we going to write the checksum?
        BEQ     %FT80

        MOV     R0, #CheckSumCMOS
        BL      Read                    ; get old checksum byte
        ADD     R0, R0, R4              ; add new data checksum
        SUB     R1, R0, R3              ; subtract old checksum
        MOV     R0, #CheckSumCMOS
        BL      Write                   ; write back new checksum

80
        Pull    "R0-R4,PC"

90
        ADD     SP, SP, #4              ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotWriteable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
329 330
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
331
 ]
Kevin Bracey's avatar
Kevin Bracey committed
332
        Pull    "R1-R4,PC"
Kevin Bracey's avatar
Kevin Bracey committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421

; *****************************************************************************
;
;       WriteSubBlock - Write a block of CMOS RAM specified by logical address.
;                       Assumes the address is valid, and will only read as much
;                       as it can in a single IIC transaction.
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy from
;       R2 = length
;
; out:  R0-R2 updated to reflect the amount written.
;       R4 incremented by sum of bytes written.
;
WriteSubBlock ROUT
        Push    "R3,R5-R6,R14"
        MOV     R6, R4
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&F0                ; [C0..F0) -> [10..40) cached
        MOVLO   R3, #&F0
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
        BHS     %FT10

; [F0..100) -> not written
        MOV     R3, #&100
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
        SUB     R14, R3, R0
        ADD     R0, R0, R14
        ADD     R1, R1, R14
        SUB     R2, R2, R14
        Pull    "R3,R5-R6,PC"

; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
 [ E2ROMSupport
; R3 = logical end of possible transaction (exclusive). Now check we don't cross page boundaries.
        MOV	R14, #0
        LDRB	R14, [R14, #NVRamPageSize]
        MOV     R5, #1
        MOV     R14, R5, LSL R14        ; R14 = (1<<pagesize)

        ADD     R5, R0, R4              ; R5 = physical start address
        ADD     R5, R5, R14
        SUB     R14, R14, #1
        BIC     R5, R5, R14             ; R5 = physical end of page with start address in
        SUB     R5, R5, R4              ; R5 = logical end of page with start address in

        CMP     R5, R3
        MOVLO   R3, R5                  ; adjust R3 to not cross page boundary
 ]

        CMP     R0, #&100               ; check it's a cacheable segment
        BHS     %FT15

        LDR     R14, =CMOSRAMCache
        Push    "R3, R4"
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being written
        MOV     R5, R1                  ; remember R1
12      LDRB    R14, [R1], #1           ; update cache copy
        STRB    R14, [R4], #1
        CMP     R4, R3
        BLO     %BT12
        MOV     R1, R5                  ; restore R1, and continue to update real memory
        Pull    "R3, R4"
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
Dan Ellis's avatar
Dan Ellis committed
422
  [ HAL
423
    	Push	"sb, R12"
Dan Ellis's avatar
Dan Ellis committed
424 425 426 427 428 429 430
    	MOV 	R5, R0	    	    	; save address
    	AddressHAL
    	CallHAL	HAL_NVMemoryType
    	AND 	R0, R0, #NVMemoryFlag_Provision
    	TEQ 	R0, #NVMemoryFlag_None

    	; If there's no NVmemory, tough - we just return.
431
    	Pull 	"sb,R12", EQ
Dan Ellis's avatar
Dan Ellis committed
432 433 434 435 436 437 438 439 440 441
    	Pull	"R0-R2", EQ
    	MOVEQ 	R2, #0	    	    	; nothing written
	Pull	"R3,R5-R6,PC", EQ

    	TEQ 	R0, #NVMemoryFlag_HAL
    	MOV 	R0, R5	    	    	; restore address
    	BNE 	%FT17	    	    	; do IIC things.

    	; Make the HAL call
    	CallHAL	HAL_NVMemoryWrite    	; returns bytes wrtten in R0
442 443 444
        MOV     R5, R0
    	Pull	"sb,R12"

Dan Ellis's avatar
Dan Ellis committed
445
    	Pull	"R0-R2"
446 447 448 449 450 451

        ADD     R0, R0, R5
        SUB     R2, R2, R5

16      SUBS    R5, R5, #1              ; update checksum
        LDRCS   R14, [R1], #1
452
        ADDCS   R6, R6, R14
453
        BCS     %BT16
454
        MOV     R4, R6
455

Dan Ellis's avatar
Dan Ellis committed
456 457 458
    	Pull	"R3,R5-R6,PC"

17
459
    	Pull	"sb,R12"
Dan Ellis's avatar
Dan Ellis committed
460 461
  ]

Kevin Bracey's avatar
Kevin Bracey committed
462 463 464
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
Kevin Bracey's avatar
Kevin Bracey committed
465
	MOV	R1, #RTCAddressPHI
Kevin Bracey's avatar
Kevin Bracey committed
466 467
  ]

468 469 470
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
471
        TST     R1, #&100               ; 2-byte address?
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        MOVNE   R0, R2, LSR #8
        STRNEB  R0, [R14], #1           ; offset (MSB)
        STRB    R2, [R14], #1           ; offset (LSB)

        SUB     R14, R14, R13
        STR     R14, [R13, #12]         ; transfer 1 length

        AND     R14, R1, #&FF
        ORR     R0, R14, #1:SHL:29      ; (retry)
        STR     R0, [R13, #4]           ; transfer 1 address
        ORR     R14, R14, #1:SHL:31     ; (no repeated start)
        STR     R14, [R13, #16]         ; transfer 2 address
        STR     R13, [R13, #8]          ; transfer 1 data

        ADD     R14, R13, #12*2+4
        LDMIA   R14, {R0-R2}
Kevin Bracey's avatar
Kevin Bracey committed
488 489 490
        SUB     R5, R3, R0              ; R5 = bytes being written
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
491 492 493 494 495 496 497 498 499 500
        STMIB   R14, {R0,R2}

        STR     R1, [R13, #20]          ; transfer 2 data
        STR     R5, [R13, #24]          ; transfer 2 length
        ADD     R0, R13, #4
        MOV     R1, #2
        BL      IIC_OpV

        LDR     R1, [R13, #20]          ; recover data pointer
        ADD     R13, R13, #12*2+4+4
Kevin Bracey's avatar
Kevin Bracey committed
501 502 503
20
        LDRB    R0, [R1], #1
        SUBS    R5, R5, #1
504
        ADD     R6, R6, R0              ; update checksum counter
Kevin Bracey's avatar
Kevin Bracey committed
505
        BNE     %BT20
Kevin Bracey's avatar
Kevin Bracey committed
506
                                        ; V clear
Kevin Bracey's avatar
Kevin Bracey committed
507 508
        MOV     R4, R6

Kevin Bracey's avatar
Kevin Bracey committed
509
	Pull	"R0,R2,R3,R5,R6,PC"
Kevin Bracey's avatar
Kevin Bracey committed
510

Neil Turton's avatar
Neil Turton committed
511 512
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
513 514
;	Read - Read a byte of CMOS RAM specified by logical address
;	ReadStraight - Read a byte of CMOS RAM specified by physical address
Kevin Bracey's avatar
Kevin Bracey committed
515
;       ReadWithError - Read a byte of CMOS RAM specified by logical address, giving error if out of range
Neil Turton's avatar
Neil Turton committed
516
;
Neil Turton's avatar
Neil Turton committed
517
; in:	R0 = address in CMOS RAM
Neil Turton's avatar
Neil Turton committed
518
;
Kevin Bracey's avatar
Kevin Bracey committed
519
; out:	R0 = data (illegal address return 0, or error for ReadWithError)
Neil Turton's avatar
Neil Turton committed
520
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
521 522 523
;

ReadStraight ROUT
Neil Turton's avatar
Neil Turton committed
524 525
	Push	"R1,R2,R14"
	B	%FT10
Neil Turton's avatar
Neil Turton committed
526

Kevin Bracey's avatar
Kevin Bracey committed
527 528 529 530 531 532 533
ReadWithError
        Push    "R1,R2,R14"
        BL      MangleCMOSAddress
        BCC     %FT10
        ADR     R0, ErrorBlock_CoreNotReadable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
534 535
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
536
 ]
Kevin Bracey's avatar
Kevin Bracey committed
537
        Pull    "R1,R2,PC"
Kevin Bracey's avatar
Kevin Bracey committed
538 539 540

        MakeErrorBlock CoreNotReadable

Neil Turton's avatar
Neil Turton committed
541
Read
Neil Turton's avatar
Neil Turton committed
542 543 544 545
	Push	"R1,R2,R14"
	BL	MangleCMOSAddress
	MOVCS	R0, #0			; pretend illegal addresses contain 0
	Pull	"R1,R2,PC", CS
Neil Turton's avatar
Neil Turton committed
546
10
Neil Turton's avatar
Neil Turton committed
547 548
	TEQ	R0, #&40		; is it Econet station number
	BEQ	%FT15	 		; if so then don't use cache
Kevin Bracey's avatar
Kevin Bracey committed
549 550 551 552 553 554 555 556 557 558 559
        CMP     R0, #&10                ; don't cache the clock
  [     E2ROMSupport
        BHS     %FT13
        MOV     R14, #0
        LDR     R14, [R14, #RTCFitted]
        TEQ     R14, #0
        BNE     %FT15
  |
        BLO     %FT15
  ]
13	CMP	R0, #&100		; check small cache limit
Kevin Bracey's avatar
Kevin Bracey committed
560 561 562
	LDRCC	R2, =CMOSRAMCache	; if in range
	LDRCCB	R0, [R2, R0]		; read from cache
	Pull	"R1,R2,PC", CC		; and exit
Neil Turton's avatar
Neil Turton committed
563 564 565
15

; else drop thru into real CMOS reading code
Dan Ellis's avatar
Dan Ellis committed
566 567

  [ HAL
568
    	Push	"R3,R4,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
569 570 571 572 573 574 575
    	MOV 	R4, R0	    	    	; save address
    	AddressHAL
    	CallHAL	HAL_NVMemoryType
    	AND 	R0, R0, #NVMemoryFlag_Provision
    	TEQ 	R0, #NVMemoryFlag_None

    	; If there's no NVmemory, pretend addresses contain 0
576
    	Pull 	"R3,R4,sb,R12", EQ
Dan Ellis's avatar
Dan Ellis committed
577 578 579 580 581 582 583 584 585 586 587 588 589
    	MOVEQ 	R0, #0
	Pull	"R1,R2,PC", EQ

    	TEQ 	R0, #NVMemoryFlag_HAL
    	MOV 	R0, R4	    	    	; restore address
    	BNE 	%FT20

    	; Make the HAL call - we have to provide a buffer.
    	SUB 	sp, sp, #4	    	; make some space on the stack
    	MOV 	R1, sp
    	MOV 	R2, #1
    	CallHAL	HAL_NVMemoryRead
    	LDRB 	R0, [sp], #4	    	; read back from stack and restore
590
    	Pull	"R3,R4,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
591 592 593
    	Pull	"R1,R2,PC"

20
594
        Pull    "R3,R4, sb,R12"
Neil Turton's avatar
Neil Turton committed
595
  ]
Neil Turton's avatar
Neil Turton committed
596

Neil Turton's avatar
Neil Turton committed
597 598 599
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
Kevin Bracey's avatar
Kevin Bracey committed
600
	MOV	R1, #RTCAddressPHI
Neil Turton's avatar
Neil Turton committed
601
  ]
Neil Turton's avatar
Neil Turton committed
602

603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
        SUB     R13, R13, #2*12+4
        MOV     R14, R13
        TST     R1, #&100
        MOVNE   R2, R0, LSR #8
        STRNEB  R2, [R14], #1           ; offset (MSB)
        STRB    R0, [R14], #1           ; offset (LSB)
        SUB     R14, R14, R13
        STR     R13, [R13, #8]          ; transfer 1 data
        STR     R14, [R13, #12]         ; transfer 1 length
        AND     R14, R1, #&FF
        ORR     R2, R14, #1:SHL:29      ; retry
        STR     R2, [R13, #4]           ; transfer 1 address
        ORR     R14, R14, #1            ; device address for read
        STR     R14, [R13, #16]         ; transfer 2 address
        ADD     R14, R13, #3
        STR     R14, [R13, #20]         ; transfer 2 data
        MOV     R14, #1
        STR     R14, [R13, #24]         ; transfer 2 length
Kevin Bracey's avatar
Kevin Bracey committed
621 622
        ADD     R0, R13, #4
        MOV     R1, #2
623 624 625
        BL      IIC_OpV
        LDRB    R0, [R13, #3]
        ADD     R13, R13, #2*12+4
Neil Turton's avatar
Neil Turton committed
626

Neil Turton's avatar
Neil Turton committed
627
	Pull	"R1,R2,PC"
Neil Turton's avatar
Neil Turton committed
628

Kevin Bracey's avatar
Kevin Bracey committed
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674

; *****************************************************************************
;
;       ReadBlock - Read a block of CMOS RAM specified by logical address
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy to
;       R2 = length
;
; out:  All registers preserved
;


ReadBlock ROUT
        Push    "R0-R3,R14"
  [     E2ROMSupport
        MOV	R14, #0
        LDRB	R14, [R14, #NVRamSize]
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
  ]

        CMP     R0, R14
        BHS     %FT90

        ADDS    R3, R0, R2              ; R3 = end address - check unsigned overflow
        BCS     %FT90
        CMP     R3, R14
        BHI     %FT90

        TEQ     R2, #0
        BEQ     %FT80

10      BL      ReadSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10
80
        Pull    "R0-R3,PC"

90
        ADD     SP, SP, #4              ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotReadable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
675 676
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
677
 ]
Kevin Bracey's avatar
Kevin Bracey committed
678
        Pull    "R1-R3,PC"
Kevin Bracey's avatar
Kevin Bracey committed
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736

; *****************************************************************************
;
;       ReadSubBlock - Read a block of CMOS RAM specified by logical address.
;                      Assumes the address is valid, and will only read as much
;                      as it can in a single IIC transaction.
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy to
;       R2 = length
;
; out:  R0-R2 updated to reflect the amount read.
;
ReadSubBlock ROUT
        Push    "R3-R5,R14"
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&F0                ; [C0..F0) -> [10..40) cached
        MOVLO   R3, #&F0
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100               ; [F0..100) -> [00..10) cached
        MOVLO   R3, #&100
        MOVLO   R4, #&00-&F0
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
; R3 = logical end of this transaction (exclusive)
        TEQ     R0, #0                  ; check it's a cacheable segment
        BEQ     %FT15
        CMP     R0, #&100
        BHS     %FT15

        LDR     R14, =CMOSRAMCache
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being read
        ADD     R0, R0, R14             ; update return R0
        SUB     R2, R2, R14             ; update return R2

12      LDRB    R14, [R4], #1
        CMP     R4, R3
        STRB    R14, [R1], #1
        BLO     %BT12
Kevin Bracey's avatar
Kevin Bracey committed
737
        Pull    "R3-R5,PC"              ; V will be clear
Kevin Bracey's avatar
Kevin Bracey committed
738 739
15
        Push    "R0-R2"
740 741
        ADD     R0, R0, R4              ; R0 = physical start address
        ADD     R3, R3, R4              ; R3 = physical end address
Dan Ellis's avatar
Dan Ellis committed
742 743
  [ HAL
    	Push	"sb"
744
        SUB     R2, R3, R0
Dan Ellis's avatar
Dan Ellis committed
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
    	MOV 	R5, R0	    	    	; save address
    	AddressHAL
    	Push	"R1-R3,R12"
    	CallHAL	HAL_NVMemoryType
    	Pull	"R1-R3,R12"
    	AND 	R0, R0, #NVMemoryFlag_Provision
    	TEQ 	R0, #NVMemoryFlag_None

    	; If there's no NVmemory, tough - we just return.
    	MOVEQ 	R2, #0	    	    	; nothing read
    	Pull 	"sb", EQ
	Pull	"R3-R5,PC", EQ

    	TEQ 	R0, #NVMemoryFlag_HAL
    	MOV 	R0, R5	    	    	; restore address
    	BNE 	%FT17	    	    	; do IIC things.

    	; Make the HAL call
    	Push	"R12"
    	CallHAL	HAL_NVMemoryRead    	; returns bytes read in R0
    	Pull	"R12"
766
        MOV     R4, R0
Dan Ellis's avatar
Dan Ellis committed
767
    	Pull	"sb"
768 769 770 771
        Pull    "R0-R2"
        ADD     R0, R0, R4
        ADD     R1, R1, R4
        SUB     R2, R2, R4
Dan Ellis's avatar
Dan Ellis committed
772 773 774 775 776 777
    	Pull	"R3-R5,PC"

17
    	Pull	"sb"
  ]

778 779
        SUB     R5, R3, R0              ; R5 = bytes being read

Kevin Bracey's avatar
Kevin Bracey committed
780 781 782
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
Kevin Bracey's avatar
Kevin Bracey committed
783
	MOV	R1, #RTCAddressPHI
Kevin Bracey's avatar
Kevin Bracey committed
784 785 786
  ]


787 788 789
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
790
        TST     R1, #&100               ; 2-byte address?
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
        MOVNE   R0, R2, LSR #8
        STRNEB  R0, [R14], #1           ; offset (MSB)
        STRB    R2, [R14], #1           ; offset (LSB)

        SUB     R14, R14, R13
        STR     R14, [R13, #12]         ; transfer 1 length

        AND     R14, R1, #&FF
        ORR     R0, R14, #1:SHL:29      ; retry
        STR     R0, [R13, #4]           ; transfer 1 address
        ORR     R14, R14, #1            ; device address for read
        STR     R14, [R13, #16]         ; transfer 2 address
        STR     R13, [R13, #8]          ; transfer 1 data

        ADD     R14, R13, #12*2+4
        LDMIA   R14, {R0-R2}
Kevin Bracey's avatar
Kevin Bracey committed
807 808
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
809 810 811 812 813 814 815 816 817 818 819 820 821
        STMIB   R14, {R0,R2}

        STR     R1, [R13, #20]          ; transfer 2 data
        STR     R5, [R13, #24]          ; transfer 2 length
        ADD     R0, R13, #4
        MOV     R1, #2
        BL      IIC_OpV

        LDR     R1, [R13, #20]          ; recover data pointer
        ADD     R1, R1, R5
        ADD     R13, R13, #12*2+4+4

        CLRV
Kevin Bracey's avatar
Kevin Bracey committed
822

Kevin Bracey's avatar
Kevin Bracey committed
823
	Pull	"R0,R2,R3-R5,PC"
Kevin Bracey's avatar
Kevin Bracey committed
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921

; *****************************************************************************
;
;       ChecksumBlock - Checksum a block of CMOS RAM specified by logical address
;                       Assumes the address is valid.
;
; in:   R0 = address in CMOS RAM
;       R1 = initial checksum
;       R2 = length
;
; out:  R1 incremented by sum of bytes in range
;


ChecksumBlock ROUT
        Push    "R0,R2,R14"

10      BL      ChecksumSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10
80
        Pull    "R0,R2,PC"


; *****************************************************************************
;
;       ChecksumSubBlock - Checksum a block of CMOS RAM specified by logical address.
;                          Assumes the address is valid, and will only read as much
;                          as it can in a single IIC transaction. Skips over
;                          239 (the checksum byte itself), and 240-255 (OTP area).
;
; in:   R0 = address in CMOS RAM
;       R1 = initial checksum
;       R2 = length
;
; out:  R0-R2 updated to reflect the data read.
;
ChecksumSubBlock ROUT
        Push    "R3-R5,R14"
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&EF                ; [C0..EF) -> [10..3F) cached
        MOVLO   R3, #&EF
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
        BHS     %FT10

;  [EF..100) -> not checksummed
        MOV     R3, #&100
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
        SUB     R14, R3, R0
        ADD     R0, R0, R14
        SUB     R2, R2, R14
        Pull    "R3-R5,PC"


; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
; R3 = logical end of this transaction (exclusive)

        TEQ     R0, #0                  ; check it's a cacheable segment
        BEQ     %FT15
        CMP     R0, #&100
        BHS     %FT15

        LDR     R14, =CMOSRAMCache
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being read
        ADD     R0, R0, R14             ; update return R0
        SUB     R2, R2, R14             ; update return R2

12      LDRB    R14, [R4], #1
        CMP     R4, R3
        ADD     R1, R1, R14
        BLO     %BT12
        Pull    "R3-R5,PC"
15
        Push    "R0-R2"
922 923
        ADD     R0, R0, R4              ; R0 = physical start address
        ADD     R3, R3, R4              ; R3 = physical end address
924
  [ HAL
925
    	Push	"sb,R12"
926 927
    	MOV 	R5, R0	    	    	; save address
    	AddressHAL
928
    	Push	"R1-R3"
929
    	CallHAL	HAL_NVMemoryType
930 931 932 933
    	Pull	"R1-R3"
    	AND 	R4, R0, #NVMemoryFlag_Provision
    	MOV 	R0, R5	    	    	; restore address
    	TEQ 	R4, #NVMemoryFlag_None
934 935
        TEQNE   R4, #NVMemoryFlag_HAL
        BNE     %FT17                   ; do IIC things.
936

937 938 939 940 941 942 943
        SUB     R14, R3, R0
        LDR     R1, [R13,#8]
        LDR     R3, [R13,#16]
        ADD     R1, R1, R14
        SUB     R3, R3, R14
        STR     R1, [R13,#8]
        STR     R3, [R13,#16]
944

945
    	TEQ 	R4, #NVMemoryFlag_None
946
    	; If there's no NVmemory, tough - we just return.
947
    	Pull 	"sb,R12", EQ
948 949 950 951
	Pull	"R0-R5,PC", EQ

        Push    "R6"
        MOV     R4, #0
952
        ADD     R6, R5, R14
953 954 955 956 957 958 959 960 961 962 963 964
        SUB     R13, R13, #4
16
        MOV     R0, R5
        MOV     R1, sp
        MOV     R2, #1
        CallHAL HAL_NVMemoryRead
        LDRB    R14, [R13]
        ADD     R4, R4, R14
        ADD     R5, R5, #1
        TEQ     R5, R6
        BNE     %BT16
        ADD     R13, R13, #4
965
        Pull    "R6,sb,R12"
966 967 968 969
        Pull    "R0-R2"
        ADD     R1,R1,R4
        Pull    "R3-R5,PC"
17
970
        Pull    "sb,R12"
971
  ]
972
        SUB     R5, R3, R0              ; R5 = bytes being read
Kevin Bracey's avatar
Kevin Bracey committed
973

Kevin Bracey's avatar
Kevin Bracey committed
974 975 976
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
Kevin Bracey's avatar
Kevin Bracey committed
977
	MOV	R1, #RTCAddressPHI
Kevin Bracey's avatar
Kevin Bracey committed
978 979
  ]

980 981 982
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
983
        TST     R1, #&100               ; 2-byte address?
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
        MOVNE   R0, R2, LSR #8
        STRNEB  R0, [R14], #1           ; offset (MSB)
        STRB    R2, [R14], #1           ; offset (LSB)

        SUB     R14, R14, R13
        STR     R14, [R13, #12]         ; transfer 1 length

        AND     R14, R1, #&FF
        ORR     R0, R14, #1:SHL:29      ; retry
        STR     R0, [R13, #4]           ; transfer 1 address
        ORR     R14, R14, #1            ; device address for read
        ORR     R14, R14, #1:SHL:30     ; checksum only please
        STR     R14, [R13, #16]         ; transfer 2 address
        STR     R13, [R13, #8]          ; transfer 1 data

        ADD     R14, R13, #12*2+4
        LDMIA   R14, {R0-R2}
Kevin Bracey's avatar
Kevin Bracey committed
1001 1002
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
1003 1004
        STMIB   R14, {R0,R2}
        MOV     R4, R1                  ; remember checksum
Kevin Bracey's avatar
Kevin Bracey committed
1005

1006 1007 1008 1009 1010
        STR     R5, [R13, #24]          ; transfer 2 length
        ADD     R0, R13, #4
        MOV     R1, #2
        BL      IIC_OpV

1011
        LDR     R1, [R13, #24]          ; read back checksum
1012 1013
        ADD     R1, R1, R4              ; update checksum
        ADD     R13, R13, #12*2+4+4
Kevin Bracey's avatar
Kevin Bracey committed
1014 1015 1016

	Pull	"R0,R2,R3-R5,PC"

Neil Turton's avatar
Neil Turton committed
1017 1018
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1019 1020
;	GetI2CAddress - Convert NVRam physical address to i2c device address
;	                and offset
Neil Turton's avatar
Neil Turton committed
1021
;
Neil Turton's avatar
Neil Turton committed
1022
; in:	R0 = NVRam physical address (&00..size of NVRam)
Neil Turton's avatar
Neil Turton committed
1023
;
Neil Turton's avatar
Neil Turton committed
1024
; out:	R0 preserved
Neil Turton's avatar
Neil Turton committed
1025
;
Neil Turton's avatar
Neil Turton committed
1026 1027 1028
;	C=0 => NVRam address is valid
;	 R0 = physical address within i2c device
;	 R1 = i2c device address for writing. Increment this device address
Kevin Bracey's avatar
Kevin Bracey committed
1029
;	      by 1 for reading. Bit 8 is set if device requires 2-byte physical address.
Neil Turton's avatar
Neil Turton committed
1030
;
Neil Turton's avatar
Neil Turton committed
1031 1032 1033 1034 1035 1036
;	C=1 => NVRam address is out of range of CMOS or E2ROM chips
;	 R0 preserved
;	 R1 preserved

  [	E2ROMSupport
GetI2CAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1037 1038 1039 1040 1041
	Push	"R14"
	MOV	R14, #0			; get no 256 byte blocks and calculate end address
	LDRB	R14, [R14, #NVRamSize]
	MOV	R14, R14, LSL #8
	CMP	R0, R14
Kevin Bracey's avatar
Kevin Bracey committed
1042
	Pull	"PC",CS 		; indicate invalid
Neil Turton's avatar
Neil Turton committed
1043

Kevin Bracey's avatar
Kevin Bracey committed
1044 1045
; address is < end address -> is valid
	MOV	R1, #0
Kevin Bracey's avatar
Kevin Bracey committed
1046 1047 1048 1049
	;LDRB	R1, [R1, #RTCFitted]    ; This causes a headache if both an RTC and NVRAM are fitted
	;TEQ	R1, #0
	;LDREQB  R1, [R1, #NVRamBase]   ; RTC overlaps bottom of NVRAM
	LDRB    R1, [R1, #NVRamBase]    ; RTC overlaps bottom of NVRAM
Kevin Bracey's avatar
Kevin Bracey committed
1050 1051 1052 1053

        CMP     R14, #2*1024            ; is the device bigger than 2K? If so, new addressing scheme
        ORRHI   R1, R1, #&100           ; set magic bit => 2 byte address
        BHI     %FT50
Neil Turton's avatar
Neil Turton committed
1054

Kevin Bracey's avatar
Kevin Bracey committed
1055 1056 1057 1058
	MOVS	R14, R0, LSR #8		; put top bits of physical address into device address
	ORRNE	R1, R1, R14, LSL #1
	ANDNE	R0, R0, #&FF		; and use address within 256 byte block
50
Kevin Bracey's avatar
Kevin Bracey committed
1059 1060
        CLC
	Pull	"PC"           		; indicate valid
Kevin Bracey's avatar
Kevin Bracey committed
1061

Neil Turton's avatar
Neil Turton committed
1062
  ]
Neil Turton's avatar
Neil Turton committed
1063 1064 1065


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
1066 1067 1068 1069 1070
;
;	MangleCMOSAddress - Convert from logical to physical address
;
;	Doesn't check if address is larger than the amount of NVRam installed
;
Kevin Bracey's avatar
Kevin Bracey committed
1071
; in:	R0 = logical address (&00...)
Neil Turton's avatar
Neil Turton committed
1072
;
Kevin Bracey's avatar
Kevin Bracey committed
1073 1074
; out:	C=0 => valid logical address
;	 R0 = physical address (&40..&FF,&10..&3F,&00..0F,&100..)
Neil Turton's avatar
Neil Turton committed
1075
;
Kevin Bracey's avatar
Kevin Bracey committed
1076
;	C=1 => invalid logical address
Neil Turton's avatar
Neil Turton committed
1077 1078
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
1079

Neil Turton's avatar
Neil Turton committed
1080
MangleCMOSAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1081 1082 1083 1084 1085 1086 1087
 [ E2ROMSupport
	Push	"R14"
	MOV	R14, #0			; read no 256 byte blocks and calculate end address
	LDRB	R14, [R14, #NVRamSize]
	MOV	R14, R14, LSL #8
	CMP	R0, R14			; if >= end address then
	Pull	"R14"
Kevin Bracey's avatar
Kevin Bracey committed
1088
        MOVCS   PC, R14 		;    invalid (exit C set)
Kevin Bracey's avatar
Kevin Bracey committed
1089 1090

	CMP	R0, #&100		; if < end address && >= &100 then
Kevin Bracey's avatar
Kevin Bracey committed
1091 1092 1093
        BLO     %FT05
        CLC
        MOV     PC, R14                 ;    valid (no mungeing)
Kevin Bracey's avatar
Kevin Bracey committed
1094
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1095
05
Kevin Bracey's avatar
Kevin Bracey committed
1096 1097
	CMP	R0, #&F0		; if < &100 && >= &f0 then
        [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1098 1099 1100 1101
        BCC     %FT10
        SUB     R0, R0, #&F0            ;    map &F0->&FF to &00->0F for OTP section
        CLC
        MOV     PC, R14
Kevin Bracey's avatar
Kevin Bracey committed
1102
        |
Kevin Bracey's avatar
Kevin Bracey committed
1103
        MOVCS   PC, R14                 ;    invalid
Kevin Bracey's avatar
Kevin Bracey committed
1104
        ]
Kevin Bracey's avatar
Kevin Bracey committed
1105
10
Neil Turton's avatar
Neil Turton committed
1106 1107 1108
	ADD	R0, R0, #&40		; now in range &40..&13F
	CMP	R0, #&100
	SUBCS	R0, R0, #(&100-&10)	; now in range &40..&FF, &10..&3F
Kevin Bracey's avatar
Kevin Bracey committed
1109 1110
        CLC
        MOV     PC, R14                 ; valid
Neil Turton's avatar
Neil Turton committed
1111 1112 1113

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1114 1115
;	ValChecksum - test to see if the CMOS checksum is OK
;
Kevin Bracey's avatar
Kevin Bracey committed
1116 1117 1118 1119 1120
;       This routine performs MangleCMOSAddress inherently.
;
;       The checksum does not include physical locations &00->&0F, even
;       if they are OTP section (as this is usually used for a unique id
;       which will be different for every machine and can't be changed).
Neil Turton's avatar
Neil Turton committed
1121
;
Neil Turton's avatar
Neil Turton committed
1122
; in:	none
Neil Turton's avatar
Neil Turton committed
1123
;
Neil Turton's avatar
Neil Turton committed
1124 1125 1126
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1127 1128
;

Neil Turton's avatar
Neil Turton committed
1129
  [ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1130

1131
ValChecksum	Entry "R1-R2"
Neil Turton's avatar
Neil Turton committed
1132

Kevin Bracey's avatar
Kevin Bracey committed
1133 1134
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1135
   [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1136 1137 1138
	MOV	R2, #0			; read number of 256 byte blocks and calculate end address
	LDRB	R2, [R2, #NVRamSize]
	MOV	R2, R2, LSL #8
Stewart Brodie's avatar
Stewart Brodie committed
1139 1140 1141
   |
	MOV	R2, #240
   ]
Kevin Bracey's avatar
Kevin Bracey committed
1142
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1143 1144

;
Kevin Bracey's avatar
Kevin Bracey committed
1145
; R1 contains the actual checksum. Compare it with the recorded checksum
Neil Turton's avatar
Neil Turton committed
1146
;
Kevin Bracey's avatar
Kevin Bracey committed
1147 1148 1149
40
	MOV	R0, #CheckSumCMOS
	BL	Read
Neil Turton's avatar
Neil Turton committed
1150
	AND	R2, R0, #&FF		; value from checksum location
Kevin Bracey's avatar
Kevin Bracey committed
1151
	AND	R0, R1, #&FF		; calculated value into R0
Neil Turton's avatar
Neil Turton committed
1152
	CMPS	R0, R2
Neil Turton's avatar
Neil Turton committed
1153

Neil Turton's avatar
Neil Turton committed
1154 1155
	EXIT
  ]
Neil Turton's avatar
Neil Turton committed
1156 1157 1158

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1159
;	MakeChecksum - calculate and write a correct checksum
Neil Turton's avatar
Neil Turton committed
1160
;
Neil Turton's avatar
Neil Turton committed
1161
; in:	none
Neil Turton's avatar
Neil Turton committed
1162
;
Neil Turton's avatar
Neil Turton committed
1163 1164
; out:	R0 = calculated checksum
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1165 1166
;

Neil Turton's avatar
Neil Turton committed
1167
	[ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1168

Neil Turton's avatar
Neil Turton committed
1169
MakeChecksum	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1170 1171 1172
	Push	"R1-R2,R14"
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1173
  [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1174 1175 1176
	MOV	R2, #0
	LDRB	R2, [R2, #NVRamSize]
	MOV	R2, R2, LSL #8
Stewart Brodie's avatar
Stewart Brodie committed
1177 1178 1179
  |
	MOV	R2, #240
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1180
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1181 1182
	MOV	R0, #CheckSumCMOS
	BL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1183
	Pull	"R1-R2,PC"
Neil Turton's avatar
Neil Turton committed
1184
	]
Neil Turton's avatar
Neil Turton committed
1185

Kevin Bracey's avatar
Kevin Bracey committed
1186 1187
        LTORG

Neil Turton's avatar
Neil Turton committed
1188 1189
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1190
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
1191
;
Neil Turton's avatar
Neil Turton committed
1192 1193 1194 1195 1196 1197 1198 1199 1200
; in:	UTC time:
;	R0 = hours
;	R1 = minutes
;	R2 = day of month
;	R3 = month
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1201
;
Kevin Bracey's avatar
Kevin Bracey committed
1202
;	If R0,R2,R5 or R6 is -1 then the time,date,year,century (respectively) will not be written
Neil Turton's avatar
Neil Turton committed
1203 1204 1205
;

SetTime ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1206
	Push	"R4, R9-R10, R14"	; save registers
Kevin Bracey's avatar
Kevin Bracey committed
1207

Kevin Bracey's avatar
Kevin Bracey committed
1208 1209 1210
	LDR	R10, =ZeroPage
	LDRB	R10, [R10, #RTCFitted]
        TEQ     R10, #0			; no RTC - just set soft copy
Kevin Bracey's avatar
Kevin Bracey committed
1211 1212 1213
        BNE     %FT20

        BL      RegToRealTime
Kevin Bracey's avatar
Kevin Bracey committed
1214
        Pull    "R4, R9-R10, PC"
Dan Ellis's avatar
Dan Ellis committed
1215

Kevin Bracey's avatar
Kevin Bracey committed
1216
20
Kevin Bracey's avatar
Kevin Bracey committed
1217 1218
	Push	"R0-R2"
	MOV	R4, R0			; copy hours in R4
Neil Turton's avatar
Neil Turton committed
1219 1220

	Push	"R1"
Kevin Bracey's avatar
Kevin Bracey committed
1221
	MOVS	R1, R5                  ; year held seperately from the RTC
Neil Turton's avatar
Neil Turton committed
1222 1223 1224 1225 1226
	MOVPL	R0, #YearCMOS
	BLPL	Write
	MOVS	R1, R6
	MOVPL	R0, #YearCMOS+1
	BLPL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1227
	Pull	"R1"
Neil Turton's avatar
Neil Turton committed
1228 1229 1230 1231

	CMP	R4, #-1			; are we writing time ?
	BEQ	%FT30

1232 1233
        SUB     R13, R13, #8
        MOV     R9, R13
Kevin Bracey's avatar
Kevin Bracey committed
1234 1235 1236
	TEQ	R10, #RTCAddressPHI
        MOVEQ   R0, #1                  ; offset to start of time (varies)
        MOVNE   R0, #0
1237
        STRB    R0, [R9], #1
Kevin Bracey's avatar
Kevin Bracey committed
1238 1239
        MOVEQ   R0, R8                  ; centiseconds (not for Dallas parts)
        BLEQ    HTBS9
1240 1241 1242 1243 1244 1245
        MOV     R0, R7                  ; seconds
        BL      HTBS9
        MOV     R0, R1                  ; minutes
        BL      HTBS9
        MOV     R0, R4                  ; hours
        BL      HTBS9
Kevin Bracey's avatar
Kevin Bracey committed
1246 1247 1248 1249
        MOV	R6, R2
	BL	%FT45
	MOV	R2, R6			; preserve D-O-M for later
        ADD	R13, R13, #8
Neil Turton's avatar
Neil Turton committed
1250

Neil Turton's avatar
Neil Turton committed
1251
30
Neil Turton's avatar
Neil Turton committed
1252
	CMP	R2, #-1			; are we writing date ?
Kevin Bracey's avatar
Kevin Bracey committed
1253
	BEQ	%FT40
Neil Turton's avatar
Neil Turton committed
1254

1255 1256
        SUB     R13, R13, #8
        MOV     R9, R13
Kevin Bracey's avatar
Kevin Bracey committed
1257 1258 1259 1260 1261
	TEQ	R10, #RTCAddressPHI
	BNE     %FT35

	; Philips specific handling
        MOV     R0, #5                  ; offset 5
1262 1263 1264 1265 1266 1267 1268
        STRB    R0, [R9], #1
        MOV     R0, R2                  ; day of month
        BL      HexToBCD
        ORR     R0, R0, R5, LSL #6      ; year in bits 6,7; day in bits 0..5
        STRB    R0, [R9], #1
        MOV     R0, R3                  ; months
        BL      HTBS9
Kevin Bracey's avatar
Kevin Bracey committed
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
	B	%FT37
35
	; Dallas specific handling
	MOV	R0, #4                  ; offset 4
	STRB    R0, [R9], #1
	MOV     R0, R2
	BL	HTBS9
	MOV	R0, R3
	BL	HTBS9
	MOV	R0, R5
	BL	HTBS9			; don't bother setting the D-O-W
37
	BL      %FT45
	ADD	R13, R13, #8
Neil Turton's avatar
Neil Turton committed
1283

Neil Turton's avatar
Neil Turton committed
1284
40
Kevin Bracey's avatar
Kevin Bracey committed
1285 1286 1287
	Pull    "R0-R2"
	BL	RTCToRealTime		; update RAM copy
	Pull	"R4, R9-R10, PC"
Dan Ellis's avatar
Dan Ellis committed
1288

Kevin Bracey's avatar
Kevin Bracey committed
1289 1290 1291 1292 1293 1294 1295 1296
45
	MOV     R0, R10
        ORR     R0, R0, #1:SHL:29
        MOV     R1, R13
        SUB     R2, R9, R13
        Push    "R14"
        BL      IIC_Op                  ; write the prepared block with retries
	Pull    "PC"
Neil Turton's avatar
Neil Turton committed
1297 1298 1299

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1300
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
1301
;
Neil Turton's avatar
Neil Turton committed
1302
; in:	-
Neil Turton's avatar
Neil Turton committed
1303
;
Neil Turton's avatar
Neil Turton committed
1304 1305 1306 1307 1308 1309 1310 1311
; out:	R0 = hours
;	R1 = minutes
;	R2 = days
;	R3 = months
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1312 1313 1314
;

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
1315
	Push	"R4, R14"
Kevin Bracey's avatar
Kevin Bracey committed
1316 1317 1318 1319 1320
        SUB     R13, R13, #(12*2)+6+1+1

        LDR	R14, =ZeroPage
        LDRB	R2, [R14, #RTCFitted]
        ORR     R14, R2, #1:SHL:29      ; retry
1321
        STR     R14, [R13, #8]          ; transfer 1 address
Kevin Bracey's avatar
Kevin Bracey committed
1322
        ADD     R0, R14, #1
1323
        STR     R0, [R13, #20]          ; transfer 2 address
Kevin Bracey's avatar
Kevin Bracey committed
1324 1325 1326
        TEQ	R2, #RTCAddressPHI
        MOVEQ   R0, #1			; PHI time starts at +1
        MOVNE   R0, #0			; DAL time starts at +0
1327
        STRB    R0, [R13, #0]
Kevin Bracey's avatar
Kevin Bracey committed
1328 1329
        STR     R13, [R13, #12]         ; transfer 1 dataptr
        MOV     R0, #1
1330 1331
        STR     R0, [R13, #16]          ; transfer 1 length
        ADD     R0, R13, #1
Kevin Bracey's avatar
Kevin Bracey committed
1332
        STR     R0, [R13, #24]          ; transfer 2 dataptr
1333 1334 1335 1336 1337 1338 1339
        MOV     R0, #6
        STR     R0, [R13, #28]          ; transfer 2 length

        ADD     R0, R13, #8
        MOV     R1, #2
        BL      IIC_OpV

Kevin Bracey's avatar
Kevin Bracey committed
1340 1341 1342 1343
	TEQ     R2, #RTCAddressPHI
	BNE	%FT50

	; Philips specific read
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
        LDRB    R0, [R13, #1]
        BL      BCDToHex
        MOV     R8, R0                  ; centiseconds
        LDRB    R0, [R13, #2]
        BL      BCDToHex
        MOV     R7, R0                  ; seconds
        LDRB    R0, [R13, #3]
        BL      BCDToHex
        MOV     R1, R0                  ; minutes
        LDRB    R0, [R13, #4]
        BL      BCDToHex
        MOV     R4, R0                  ; hours
        LDRB    R0, [R13, #5]
        AND     R0, R0, #&3F            ; day of month (clear year bits)
        BL      BCDToHex
        MOV     R2, R0
        LDRB    R0, [R13, #6]
        AND     R0, R0, #&1F            ; month (clear day of week bits)
        BL      BCDToHex
        MOV     R3, R0
Kevin Bracey's avatar
Kevin Bracey committed
1364
	B	ReadTimeYear
Neil Turton's avatar
Neil Turton committed
1365

Kevin Bracey's avatar
Kevin Bracey committed
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
50
	; Dallas specific read
        MOV     R8, #0                  ; centiseconds
        LDRB    R0, [R13, #1]
        BL      BCDToHex
        MOV     R7, R0                  ; seconds
        LDRB    R0, [R13, #2]
        BL      BCDToHex
        MOV     R1, R0                  ; minutes
        LDRB    R0, [R13, #3]
        BL      BCDToHex
        MOV     R4, R0                  ; hours
        LDRB    R0, [R13, #5]
        BL      BCDToHex
        MOV     R2, R0                  ; day of month
        LDRB    R0, [R13, #6]
        BL      BCDToHex
        MOV     R3, R0                  ; month

ReadTimeYear
	ADD     R13, R13, #(12*2)+6+1+1
Neil Turton's avatar
Neil Turton committed
1387 1388 1389 1390 1391 1392 1393 1394
	MOV	R0, #YearCMOS
	BL	Read
	MOV	R5, R0			; year (lo)
	MOV	R0, #YearCMOS+1
	BL	Read
	MOV	R6, R0			; year (hi)

	MOV	R0, R4			; put hours in R0
Neil Turton's avatar
Neil Turton committed
1395

Kevin Bracey's avatar
Kevin Bracey committed
1396
	TEQ	R2, #0			; Ensure day/month are non-zero (LRust, fix RP-0370)
Neil Turton's avatar
Neil Turton committed
1397 1398 1399
	MOVEQ	R2, #1			; No then force 1st
	TEQ	R3, #0			; Invalid month?
	MOVEQ	R3, #1			; Yes then force Jan
Kevin Bracey's avatar
Kevin Bracey committed
1400

Neil Turton's avatar
Neil Turton committed
1401
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1402

Kevin Bracey's avatar
Kevin Bracey committed
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
; *****************************************************************************
;
;       InitRTC - Force the clock into a known state (incase of new battery)
;
;  in:  R0 = RTC IIC address

InitRTC
	Push    "R0-R2, R14"
	SUB	R13, R13, #4
	MOV	R1, R13
	TEQ	R0, #RTCAddressPHI
	BEQ	%FT60
1415
	ORR     R0, R0, #1:SHL:29
Kevin Bracey's avatar
Kevin Bracey committed
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
	MOV	R2, #0			; to write 0 to address ptr
	STRB	R2, [R1]
	MOV	R2, #1
	BL	IIC_Op
	ORR	R0, R0, #1
	BL	IIC_Op
	LDRB	R2, [R1]
	ANDS	R2, R2, #&80		; test clock disabled bit
	BEQ	%FT65
	EOR	R0, R0, #1
	DebugTX "Forced RTC on"
60
1428
	ORR     R0, R0, #1:SHL:29
Kevin Bracey's avatar
Kevin Bracey committed
1429 1430 1431 1432 1433 1434 1435 1436
	MOV     R2, #0
	STR	R2, [R1]
	MOV	R2, #2			; to write 0 to control reg 0
	BL      IIC_Op
65
	ADD	R13, R13, #4
	Pull    "R0-R2, PC"

Neil Turton's avatar
Neil Turton committed
1437 1438
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1439
;	InitCMOSCache - Initialise cache of CMOS RAM
Dan Ellis's avatar
Dan Ellis committed
1440 1441 1442
;  in: -
;
;  out: R0 = 0 for failure
Neil Turton's avatar
Neil Turton committed
1443

1444
InitCMOSCache	Entry "r1-r6, sb,r12"
Neil Turton's avatar
Neil Turton committed
1445 1446
    [	E2ROMSupport

Kevin Bracey's avatar
Kevin Bracey committed
1447 1448 1449 1450
	; Need to set the slowest speed so we can probe
	LDR     R4, =ZeroPage
	MOV     R3, #10         ; Default speed setting (5s delays)
	STRB    R3, [R4, #NVRamSpeed]
Kevin Bracey's avatar
Kevin Bracey committed
1451

Kevin Bracey's avatar
Kevin Bracey committed
1452 1453 1454
	; Have we got an RTC ?
	LDR 	R2, =ZeroPage
	MOV	R4, #0
1455
	MOV	R0, #RTCAddressDAL
Kevin Bracey's avatar
Kevin Bracey committed
1456 1457
	BL	DummyAccess
	BVC	%FT13
1458
	MOV	R0, #RTCAddressPHI
Kevin Bracey's avatar
Kevin Bracey committed
1459 1460 1461 1462 1463
	BL	DummyAccess
	STRVSB  R4, [R2, #RTCFitted]
13
	STRVCB  R0, [R2, #RTCFitted]
	BLVC    InitRTC
Neil Turton's avatar
Neil Turton committed
1464

Dan Ellis's avatar
Dan Ellis committed
1465 1466 1467 1468
 [ HAL
        AddressHAL
    	CallHAL	HAL_NVMemoryType
    	ANDS 	R0, R0, #NVMemoryFlag_Provision
Kevin Bracey's avatar
Kevin Bracey committed
1469
        BEQ     InitCMOSCache_NoCMOS
Dan Ellis's avatar
Dan Ellis committed
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
    	MOV 	R5, R0

    	; If it's only a maybe, then we probe
    	TEQ 	R5, #NVMemoryFlag_MaybeIIC
    	BEQ 	%FT03

    	; Else we read the size

    	CallHAL	HAL_NVMemorySize	; returns number of bytes but..
    	MOV 	R0, R0, LSR#8	    	; .. expecting no. of 256 blocks
    	STRB 	R0, [R4, #NVRamSize]

1482 1483 1484 1485 1486 1487 1488 1489 1490
        TST     R5, #NVMemoryFlag_ProtectAtEnd
        STREQB  R0, [R4, #NVRamWriteSize]
        BEQ     %FT02
        CallHAL HAL_NVMemoryProtectedSize
        LDRB    R1, [R4, #NVRamSize]
        SUB     R0, R1, R0, LSR#8
        STRB    R0, [R4, #NVRamWriteSize]

02
Kevin Bracey's avatar
Kevin Bracey committed
1491 1492 1493 1494 1495 1496 1497 1498 1499
        CallHAL HAL_NVMemoryPageSize    ; returns size in bytes but..
        TEQ     R0, #0                  ; .. expecting power of 2
        MVNEQ   R0, #0
        MOV     R1, #0
22      MOVS    R0, R0, LSR #1
        ADDNE   R1, R1, #1
        BNE     %BT22
        STRB    R1, [R4, #NVRamPageSize]

Dan Ellis's avatar
Dan Ellis committed
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
    	CallHAL	HAL_NVMemoryIICAddress
    	STRB 	R0, [R4, #NVRamBase]

    	MOV 	R0, #0
    	CallHAL	HAL_IICType
    	MOV 	R3, #10
    	TST 	R0, #IICFlag_Fast
    	MOVNE	R3, #3
    	TST 	R0, #IICFlag_HighSpeed
    	MOVNE	R3, #1
    	STRB	R3, [R4, #NVRamSpeed]

    	; If we're using IIC then read in the cache manually
Kevin Bracey's avatar
Kevin Bracey committed
1513
        AND	R0, R5, #NVMemoryFlag_Provision
Dan Ellis's avatar
Dan Ellis committed
1514 1515 1516 1517 1518 1519 1520 1521 1522
    	TEQ 	R0, #NVMemoryFlag_IIC
    	BEQ   	%FT06

    	; Else use HAL routine.
    	MOV 	R0, #0
    	LDR 	R1, =CMOSRAMCache
    	MOV 	R2, #&100
    	CallHAL	HAL_NVMemoryRead
    	TEQ 	R0, #&100
Kevin Bracey's avatar
Kevin Bracey committed
1523
    	MOVNE	R0, #0			; Failure exit condition
Dan Ellis's avatar
Dan Ellis committed
1524 1525 1526
    	EXIT
03
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1527 1528 1529

;	No HAL,so determine what hardware we've got fitted by probing,
;	R4 holds the number of 256 byte blocks that we've found
Dan Ellis's avatar
Dan Ellis committed
1530

Robert Catherall's avatar
Robert Catherall committed
1531
        MOV     R3, #10         ; assume 100kHz to start with
Kevin Bracey's avatar
Kevin Bracey committed
1532
        MOV     R5, #4          ; assume 16 byte page size to start with
1533
        MOV     R6, #0          ; assume not protected
Kevin Bracey's avatar
Kevin Bracey committed
1534

Kevin Bracey's avatar
Kevin Bracey committed
1535
; Have we got a 2K device ?
Kevin Bracey's avatar
Kevin Bracey committed
1536 1537 1538 1539 1540 1541
        MOV     r1, #E2ROMAddress2K
	MOV	r0, #(E2ROMAddress2K+14)
	BL	DummyAccess
	MOVVC	R4, #8
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
	BVC	%FT5
Neil Turton's avatar
Neil Turton committed
1542

1543
; Have we got a 16K device ?
Kevin Bracey's avatar
Kevin Bracey committed
1544 1545 1546 1547 1548 1549
        MOV     r1, #E2ROMAddress16K
	MOV	r0, #E2ROMAddress16K
	BL	DummyAccess
	MOVVC	R4, #64
        MOVVC   R5, #6          ; 64 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
1550 1551
        BVC     %FT5

1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
; Have we got a 4K device?
        MOV     r1, #E2ROMAddress4K
	MOV	r0, #E2ROMAddress4K
	BL	DummyAccess
	MOVVC	R4, #16
        MOVVC   R6, #12         ; Only bottom 3K writable
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
        BVC     %FT5

1562 1563 1564 1565 1566
; Have we got an 8K device?
        MOV     r1, #E2ROMAddress8K
	MOV	r0, #E2ROMAddress8K
	BL	DummyAccess
	MOVVC	R4, #32
1567 1568 1569 1570 1571 1572 1573 1574 1575
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
        BVC     %FT5

; Have we got a protected 8K device?
        MOV     r1, #E2ROMAddress8K_prot
	MOV	r0, #E2ROMAddress8K_prot
	BL	DummyAccess
	MOVVC	R4, #32
1576
        MOVVC   R6, #24         ; Only bottom 6K writable
1577 1578
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
Robert Catherall's avatar
Robert Catherall committed
1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
        BVC     %FT5

; Have we got a 32K device?
        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.5s delays - 1MHz part)
Dan Ellis's avatar
Dan Ellis committed
1589
    	BVC 	%FT5
Robert Catherall's avatar
Robert Catherall committed
1590

Kevin Bracey's avatar
Kevin Bracey committed
1591 1592 1593
; Any storeage in the Philips RTC? (Dallas capacity is tiny,ignored)
        MOV     R1, #RTCAddressPHI
        MOV     R0, #RTCAddressPHI
Dan Ellis's avatar
Dan Ellis committed
1594 1595 1596 1597 1598
    	BL  	DummyAccess
        MOV     R5, #8          ; 256 byte page size for CMOS
    	BVC 	%FT5

; We ain't got anything!
Kevin Bracey's avatar
Kevin Bracey committed
1599 1600 1601 1602 1603 1604 1605
InitCMOSCache_NoCMOS
        LDR     R2, =ZeroPage
        MOV     R5, #8
        STRB    R5, [R2, #NVRamPageSize]        ; Act as though we have 256 bytes of
        MOV     R1, #1                          ; single page CMOS.
        STRB    R1, [R2, #NVRamSize]
        STRB    R1, [R2, #NVRamWriteSize]
Kevin Bracey's avatar
Kevin Bracey committed
1606
    	MOV 	R0, #0		; Exit failure
Dan Ellis's avatar
Dan Ellis committed
1607
    	EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1608 1609

5
Neil Turton's avatar
Neil Turton committed
1610
	; Set the NVRam count
Kevin Bracey's avatar
Kevin Bracey committed
1611 1612 1613
	STRB    R1, [R2, #NVRamBase]
	STRB	R4, [R2, #NVRamSize]
        STRB    R5, [R2, #NVRamPageSize]
1614 1615 1616
        TEQ     R6, #0
        MOVEQ   R6, R4
        STRB    R6, [R2, #NVRamWriteSize]
Robert Catherall's avatar
Robert Catherall committed
1617 1618 1619

        CMP     R3, #I2Cticks   ; clamp speed to maximum bus speed
        MOVLO   R3, #I2Cticks
Kevin Bracey's avatar
Kevin Bracey committed
1620
        STRB    R3, [R2, #NVRamSpeed]
Dan Ellis's avatar
Dan Ellis committed
1621 1622
06
	; Initialise the cache
Kevin Bracey's avatar
Kevin Bracey committed
1623
	LDR	R3, =CMOSRAMCache
Neil Turton's avatar
Neil Turton committed
1624

Kevin Bracey's avatar
Kevin Bracey committed
1625 1626 1627 1628 1629 1630 1631 1632 1633
        TEQ     R4, #8                  ; check for 2K part
	MOVNE	r0, #&00		; if not, then start at 0 anyway and read non-OTP data into location 0..15
        BNE     %FT07
	BL	ReadOTPArea
	MOV	r0, #&10		; read rest of it from 16 onwards
07
        BL      GetI2CAddress           ; and convert to device address and offset
        MOV     R2, R0                  ; save the offset
        MOV     R4, #&100               ; stop at &100
Neil Turton's avatar
Neil Turton committed
1634
    |
Kevin Bracey's avatar
Kevin Bracey committed
1635 1636 1637 1638 1639
    	; No E2ROM support,assume a Philips RTC
    	MOV	R1, #RTCAddressPHI
    	MOV	R2, #&10
    	MOV	R4, #&100		; stop at address &100
    	LDR	R3, =CMOSRAMCache
Neil Turton's avatar
Neil Turton committed
1640
    ]
1641 1642 1643

        ; Note - R4 MUST be &100 to prevent crossover between 256-byte pages
        ; (for devices with multiple addresses)
Kevin Bracey's avatar
Kevin Bracey committed
1644
09
Neil Turton's avatar
Neil Turton committed
1645

1646 1647 1648 1649 1650
        SUB     R13, R13, #2*12+4
        AND     R0, R1, #&FF
        STR     R0, [R13, #4]           ; transfer 1 address
        ADD     R0, R0, #1              ; read address
        STR     R0, [R13, #16]          ; transfer 2 address
Kevin Bracey's avatar
Kevin Bracey committed
1651
        TST     R1, #&100               ; 2-byte address?
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670
        MOV     R14, R13
        MOVNE   R0, R2, LSR #8
        STRNEB  R0, [R14], #1           ; memory word address (MSB)
        STRB    R2, [R14], #1           ; memory word address (LSB)
        STR     R13, [R13, #8]          ; transfer 1 data
        SUB     R14, R14, R13
        STR     R14, [R13, #12]         ; transfer 1 length
        ADD     R14, R3, R2
        STR     R14, [R13, #20]         ; transfer 2 data
        SUB     R14, R4, R2
        STR     R14, [R13, #24]         ; transfer 2 length

        ADD     R0, R13, #4
        MOV     R1, #2
        BL      IIC_OpV

        ADD     R13, R13, #2*12+4
        MOV     R0, #1
        EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1671 1672 1673

   [ E2ROMSupport
ReadOTPArea Entry
1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
        SUB     R13, R13, #2*12+4
        MOV     R0, #0
        STRB    R0, [R13, #0]           ; offset 0
        MOV     R0, #E2ROMAddress2K_OTP
        STR     R0, [R13, #4]           ; transfer 1 address
        STR     R13, [R13, #8]          ; transfer 1 data
        MOV     R0, #1
        STR     R0, [R13, #12]          ; transfer 1 length
        MOV     R0, #E2ROMAddress2K_OTP + 1
        STR     R0, [R13, #16]          ; transfer 2 address
        STR     R3, [R13, #20]          ; transfer 2 data
        MOV     R0, #16
        STR     R0, [R13, #24]          ; transfer 2 length
        ADD     R0, R13, #4
        MOV     R1, #2
        BL      IIC_OpV
        ADD     R13, R13, #2*12+4
        EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1692
   ]
Neil Turton's avatar
Neil Turton committed
1693

Neil Turton's avatar
Neil Turton committed
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
; *****************************************************************************
;
;	DummyAccess - do a dummy access of the specified device to find out
;	              if it is present
;
; in:	R0 = Write address of device
;
; out:	All registers preserved
;	V=0 => device is present
;	V=1 => device is not present

  [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1706
DummyAccess
1707

Kevin Bracey's avatar
Kevin Bracey committed
1708 1709 1710 1711 1712 1713 1714 1715 1716
 [ {TRUE}
        ; Blooming 80321 HW IIC can't do just START address STOP
	Entry   "R0-R2",4
        ORR     R0, R0, #1
        MOV     R1, R13
        MOV     R2, #1
        BL      IIC_Op
 |
	Entry   "R1,R2"
1717 1718 1719
        MOV     R1, #0
        MOV     R2, #0
        BL      IIC_Op
Kevin Bracey's avatar
Kevin Bracey committed
1720
 ]
Neil Turton's avatar
Neil Turton committed
1721 1722 1723 1724

	EXIT				; Exit with V set appropriately
  ]

Kevin Bracey's avatar
Kevin Bracey committed
1725 1726 1727 1728 1729 1730 1731
; *****************************************************************************
;
;       SWI OS_NVMemory
;
; in:   R0 = reason code
;

1732
NVMemorySWI     Entry
Kevin Bracey's avatar
Kevin Bracey committed
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
        BL      NVMemorySub
        PullEnv
        ORRVS   LR, LR, #V_bit
        ExitSWIHandler

NVMemorySub
        CMP     R0, #4
        ADDLS   PC, PC, R0, LSL #2
        B       NVMemory_Unknown
        B       NVMemory_Size
        B       NVMemory_Read
        B       NVMemory_Write
        B       NVMemory_ReadBlock
        B       NVMemory_WriteBlock

NVMemory_Unknown
        ADRL    R0, ErrorBlock_HeapBadReason
 [ International
        Push    LR
        BL      TranslateError
        Pull    LR
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1755
        RETURNVS
Kevin Bracey's avatar
Kevin Bracey committed
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770

; -----------------------------------------------------------------------------
; OS_NVMemory 0 - find NV memory size
;
; in:   R0 = 0
;
; out:  R1 = NV memory size in bytes
;
NVMemory_Size
  [     E2ROMSupport
        LDRB    R1, [R0, #NVRamSize]
        MOV     R1, R1, LSL #8
  |
        MOV     R1, #240
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1771
        MOV     PC, LR
Kevin Bracey's avatar
Kevin Bracey committed
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781

; -----------------------------------------------------------------------------
; OS_NVMemory 1 - read a byte
;
; in:   R0 = 1
;       R1 = location
;
; out:  R2 = value
;
NVMemory_Read
1782 1783
        Entry   "R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1784
        BIC     R0, R4, #I32_bit
1785
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1786 1787 1788 1789 1790
        MOV     R0, R1
        BL      ReadWithError
        MOVVC   R2, R0
        MOVVC   R0, #1          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1791
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 2 - write a byte
;
; in:   R0 = 1
;       R1 = location
;       R2 = value
;
NVMemory_Write ROUT
        [ ProtectStationID
        TEQ     R1, #0          ; just ignore writes to byte 0
        MOVEQ   PC, R14
        ]
1806 1807
        Entry   "R1,R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1808
        BIC     R0, R4, #I32_bit
1809
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1810 1811 1812 1813 1814
        MOV     R0, R1
        MOV     R1, R2
        BL      WriteWithError
        MOVVC   R0, #2          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1815
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 3 - read a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_ReadBlock
1827
        Entry   "R1-R4"
Kevin Bracey's avatar
Kevin Bracey committed
1828
        MOV     R4, PC
1829
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1830
        BIC     R0, R4, #I32_bit
1831
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1832 1833 1834 1835 1836 1837
        MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      ReadBlock
        MOVVC   R0, #3          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1838
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 4 - write a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_WriteBlock ROUT
1850 1851
        Entry   "R1-R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1852
        BIC     R0, R4, #I32_bit
1853
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867
        [ ProtectStationID
        TEQ     R1, #0
        BNE     %FT10
        ADD     R1, R1, #1
        ADD     R2, R2, #1
        TEQ     R3, #0
        SUBNE   R3, R3, #1      ; steer clear of station ID
        ]
10      MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      WriteBlock
        MOVVC   R0, #4          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1868
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1869 1870
        EXIT

Neil Turton's avatar
Neil Turton committed
1871
	END