i2cutils 56.8 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

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

16      SUBS    R5, R5, #1              ; update checksum
451
        LDRCSB  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
        CMP     R0, #&10                ; don't cache the clock
  [     E2ROMSupport
        BHS     %FT13
552
        ; If there's no RTC, read dummy values from the cache
Kevin Bracey's avatar
Kevin Bracey committed
553
        MOV     R14, #0
554
        LDR     R14, [R14, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
555 556 557 558 559 560
        TEQ     R14, #0
        BNE     %FT15
  |
        BLO     %FT15
  ]
13	CMP	R0, #&100		; check small cache limit
Kevin Bracey's avatar
Kevin Bracey committed
561 562 563
	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
564 565 566
15

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

  [ HAL
569
    	Push	"R3,R4,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
570 571 572 573 574 575 576
    	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
577
    	Pull 	"R3,R4,sb,R12", EQ
Dan Ellis's avatar
Dan Ellis committed
578 579 580 581 582 583 584 585 586 587 588 589 590
    	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
591
    	Pull	"R3,R4,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
592 593 594
    	Pull	"R1,R2,PC"

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

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

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
        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
622 623
        ADD     R0, R13, #4
        MOV     R1, #2
624 625 626
        BL      IIC_OpV
        LDRB    R0, [R13, #3]
        ADD     R13, R13, #2*12+4
Neil Turton's avatar
Neil Turton committed
627

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

Kevin Bracey's avatar
Kevin Bracey committed
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 675

; *****************************************************************************
;
;       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
676 677
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
678
 ]
Kevin Bracey's avatar
Kevin Bracey committed
679
        Pull    "R1-R3,PC"
Kevin Bracey's avatar
Kevin Bracey committed
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 737

; *****************************************************************************
;
;       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
738
        Pull    "R3-R5,PC"              ; V will be clear
Kevin Bracey's avatar
Kevin Bracey committed
739 740
15
        Push    "R0-R2"
741 742
        ADD     R0, R0, R4              ; R0 = physical start address
        ADD     R3, R3, R4              ; R3 = physical end address
Dan Ellis's avatar
Dan Ellis committed
743 744
  [ HAL
    	Push	"sb"
745
        SUB     R2, R3, R0
Dan Ellis's avatar
Dan Ellis committed
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
    	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"
767
        MOV     R4, R0
Dan Ellis's avatar
Dan Ellis committed
768
    	Pull	"sb"
769 770 771 772
        Pull    "R0-R2"
        ADD     R0, R0, R4
        ADD     R1, R1, R4
        SUB     R2, R2, R4
Dan Ellis's avatar
Dan Ellis committed
773 774 775 776 777 778
    	Pull	"R3-R5,PC"

17
    	Pull	"sb"
  ]

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

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


788 789 790
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
791
        TST     R1, #&100               ; 2-byte address?
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
        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
808 809
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
810 811 812 813 814 815 816 817 818 819 820 821 822
        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
823

Kevin Bracey's avatar
Kevin Bracey committed
824
	Pull	"R0,R2,R3-R5,PC"
Kevin Bracey's avatar
Kevin Bracey committed
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 922

; *****************************************************************************
;
;       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"
923 924
        ADD     R0, R0, R4              ; R0 = physical start address
        ADD     R3, R3, R4              ; R3 = physical end address
925
  [ HAL
926
    	Push	"sb,R12"
927 928
    	MOV 	R5, R0	    	    	; save address
    	AddressHAL
929
    	Push	"R1-R3"
930
    	CallHAL	HAL_NVMemoryType
931 932 933 934
    	Pull	"R1-R3"
    	AND 	R4, R0, #NVMemoryFlag_Provision
    	MOV 	R0, R5	    	    	; restore address
    	TEQ 	R4, #NVMemoryFlag_None
935 936
        TEQNE   R4, #NVMemoryFlag_HAL
        BNE     %FT17                   ; do IIC things.
937

938 939 940 941 942 943 944
        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]
945

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

        Push    "R6"
        MOV     R4, #0
953
        ADD     R6, R5, R14
954 955 956 957 958 959 960 961 962 963 964 965
        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
966
        Pull    "R6,sb,R12"
967 968 969 970
        Pull    "R0-R2"
        ADD     R1,R1,R4
        Pull    "R3-R5,PC"
17
971
        Pull    "sb,R12"
972
  ]
973
        SUB     R5, R3, R0              ; R5 = bytes being read
Kevin Bracey's avatar
Kevin Bracey committed
974

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

981 982 983
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
984
        TST     R1, #&100               ; 2-byte address?
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
        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
1002 1003
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
1004 1005
        STMIB   R14, {R0,R2}
        MOV     R4, R1                  ; remember checksum
Kevin Bracey's avatar
Kevin Bracey committed
1006

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

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

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

Neil Turton's avatar
Neil Turton committed
1018 1019
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1020 1021
;	GetI2CAddress - Convert NVRam physical address to i2c device address
;	                and offset
Neil Turton's avatar
Neil Turton committed
1022
;
Neil Turton's avatar
Neil Turton committed
1023
; in:	R0 = NVRam physical address (&00..size of NVRam)
Neil Turton's avatar
Neil Turton committed
1024
;
Neil Turton's avatar
Neil Turton committed
1025
; out:	R0 preserved
Neil Turton's avatar
Neil Turton committed
1026
;
Neil Turton's avatar
Neil Turton committed
1027 1028 1029
;	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
1030
;	      by 1 for reading. Bit 8 is set if device requires 2-byte physical address.
Neil Turton's avatar
Neil Turton committed
1031
;
Neil Turton's avatar
Neil Turton committed
1032 1033 1034 1035 1036 1037
;	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
1038 1039 1040 1041 1042
	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
1043
	Pull	"PC",CS 		; indicate invalid
Neil Turton's avatar
Neil Turton committed
1044

Kevin Bracey's avatar
Kevin Bracey committed
1045 1046
; address is < end address -> is valid
	MOV	R1, #0
1047
	;LDR	R1, [R1, #RTCFitted]    ; This causes a headache if both an RTC and NVRAM are fitted
Kevin Bracey's avatar
Kevin Bracey committed
1048 1049 1050
	;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
1051 1052 1053 1054

        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
1055

Kevin Bracey's avatar
Kevin Bracey committed
1056 1057 1058 1059
	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
1060 1061
        CLC
	Pull	"PC"           		; indicate valid
Kevin Bracey's avatar
Kevin Bracey committed
1062

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


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
1067 1068 1069 1070 1071
;
;	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
1072
; in:	R0 = logical address (&00...)
Neil Turton's avatar
Neil Turton committed
1073
;
Kevin Bracey's avatar
Kevin Bracey committed
1074 1075
; out:	C=0 => valid logical address
;	 R0 = physical address (&40..&FF,&10..&3F,&00..0F,&100..)
Neil Turton's avatar
Neil Turton committed
1076
;
Kevin Bracey's avatar
Kevin Bracey committed
1077
;	C=1 => invalid logical address
Neil Turton's avatar
Neil Turton committed
1078 1079
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
1080

Neil Turton's avatar
Neil Turton committed
1081
MangleCMOSAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1082 1083 1084 1085 1086 1087 1088
 [ 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
1089
        MOVCS   PC, R14 		;    invalid (exit C set)
Kevin Bracey's avatar
Kevin Bracey committed
1090 1091

	CMP	R0, #&100		; if < end address && >= &100 then
Kevin Bracey's avatar
Kevin Bracey committed
1092 1093 1094
        BLO     %FT05
        CLC
        MOV     PC, R14                 ;    valid (no mungeing)
Kevin Bracey's avatar
Kevin Bracey committed
1095
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1096
05
Kevin Bracey's avatar
Kevin Bracey committed
1097 1098
	CMP	R0, #&F0		; if < &100 && >= &f0 then
        [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1099 1100 1101 1102
        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
1103
        |
Kevin Bracey's avatar
Kevin Bracey committed
1104
        MOVCS   PC, R14                 ;    invalid
Kevin Bracey's avatar
Kevin Bracey committed
1105
        ]
Kevin Bracey's avatar
Kevin Bracey committed
1106
10
Neil Turton's avatar
Neil Turton committed
1107 1108 1109
	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
1110 1111
        CLC
        MOV     PC, R14                 ; valid
Neil Turton's avatar
Neil Turton committed
1112 1113 1114

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1115 1116
;	ValChecksum - test to see if the CMOS checksum is OK
;
Kevin Bracey's avatar
Kevin Bracey committed
1117 1118 1119 1120 1121
;       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
1122
;
Neil Turton's avatar
Neil Turton committed
1123
; in:	none
Neil Turton's avatar
Neil Turton committed
1124
;
Neil Turton's avatar
Neil Turton committed
1125 1126 1127
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1128 1129
;

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

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

Kevin Bracey's avatar
Kevin Bracey committed
1134 1135
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1136
   [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1137 1138 1139
	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
1140 1141 1142
   |
	MOV	R2, #240
   ]
Kevin Bracey's avatar
Kevin Bracey committed
1143
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1144 1145

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

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

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

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

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

Kevin Bracey's avatar
Kevin Bracey committed
1187 1188
        LTORG

Neil Turton's avatar
Neil Turton committed
1189 1190
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1191
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
1192
;
Neil Turton's avatar
Neil Turton committed
1193 1194 1195
; in:	UTC time:
;	R0 = hours
;	R1 = minutes
1196 1197
;	R2 = day of month (1-based)
;	R3 = month (1-based)
Neil Turton's avatar
Neil Turton committed
1198 1199 1200 1201
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1202
;
1203
;	If R0,R2,R5 or R6 is -1 then the time,date,year,century (respectively) will not be written. However if R2=-1, R5 & R6 will also be -1, so only R0 (for time) and R2 (for D/M/Y) need checking.
Neil Turton's avatar
Neil Turton committed
1204 1205 1206
;

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

Kevin Bracey's avatar
Kevin Bracey committed
1209
	LDR	R10, =ZeroPage
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
	LDR	R10, [R10, #RTCFitted]
 [ HAL
        CMP	R10, #2048 ; Is it an I2C address or HALDevice_RTC ptr?
        BLO	%FT15
	Push	"R0-R3,R12"
	MOV	R4, R0			; copy hours in R4
        ; Prepare BCD data on stack
        ASSERT (RTCTimeStruct_BCD_Size :AND: 3)=0
        SUB	R13, R13, #RTCTimeStruct_BCD_Size
        MOV	R9, R13
        ; Ensure struct matches our setting order
        ASSERT RTCTimeStruct_BCD_Centiseconds = 0
        ASSERT RTCTimeStruct_BCD_Seconds = 1
        ASSERT RTCTimeStruct_BCD_Minutes = 2
        ASSERT RTCTimeStruct_BCD_Hours = 3
        ASSERT RTCTimeStruct_BCD_DayOfMonth = 4
        ASSERT RTCTimeStruct_BCD_Month = 5
        ASSERT RTCTimeStruct_BCD_YearLO = 6
        ASSERT RTCTimeStruct_BCD_YearHI = 7
        ; Are we setting the time?
        CMP	R4, #-1
        STREQ	R4, [R9], #4 ; Conveniently, 4 bytes of time info
        BEQ	%FT11
        MOV	R0, R8
        BL	HTBS9
        MOV	R0, R7
        BL	HTBS9
        MOV	R0, R1
        BL	HTBS9
        MOV	R0, R4
        BL	HTBS9
11
	; Are we setting the date?
	CMP	R2, #-1
	STREQ	R2, [R9], #4 ; Conveniently, 4 bytes of date info
	BEQ	%FT12
        LDRB	R1, [R10, #HALDevice_RTCFormatFlags]
        MOV	R0, R2
        TST	R1, #RTCFormatFlags_BCD_1BasedDay
        SUBEQ	R0, R0, #1
        BL	HTBS9
        TST	R1, #RTCFormatFlags_BCD_1BasedMonth
        MOV	R0, R3
        SUBEQ	R0, R0, #1
        BL	HTBS9
1255 1256 1257 1258 1259
        TST	R1, #RTCFormatFlags_BCD_YearLOIsGood
        ANDEQ	R0, R5, #3 ; 2 bit YearLO
        STREQB	R0, [R9], #1
        MOVNE	R0, R5 ; BCD YearLO
        BLNE	HTBS9
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
        MOV	R0, R6
        BL	HTBS9
12
        SUB	R1, R9, #8
        MOV	R0, R10
        ADRL	R2, HALRTC_IICOp
        MOV	LR, PC
        LDR	PC, [R10, #HALDevice_RTCWriteTime]
	; Unfortunately, we don't do anything with the return code at the moment.
13
	ADD	R13, R13, #RTCTimeStruct_BCD_Size ; RTCTimeStruct
	Pull	"R0-R3,R12"
	BL	RTCToRealTime
	Pull	"R4, R9-R10, PC"
15
 ] ; HAL
 [ RTCSupport :LOR: :LNOT: HAL
Kevin Bracey's avatar
Kevin Bracey committed
1277
        TEQ     R10, #0			; no RTC - just set soft copy
Kevin Bracey's avatar
Kevin Bracey committed
1278
        BNE     %FT20
1279
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1280
        BL      RegToRealTime
Kevin Bracey's avatar
Kevin Bracey committed
1281
        Pull    "R4, R9-R10, PC"
1282
 [ RTCSupport  :LOR: :LNOT: HAL
Kevin Bracey's avatar
Kevin Bracey committed
1283
20
Kevin Bracey's avatar
Kevin Bracey committed
1284 1285
	Push	"R0-R2"
	MOV	R4, R0			; copy hours in R4
Neil Turton's avatar
Neil Turton committed
1286 1287

	Push	"R1"
Kevin Bracey's avatar
Kevin Bracey committed
1288
	MOVS	R1, R5                  ; year held seperately from the RTC
Neil Turton's avatar
Neil Turton committed
1289 1290 1291 1292 1293
	MOVPL	R0, #YearCMOS
	BLPL	Write
	MOVS	R1, R6
	MOVPL	R0, #YearCMOS+1
	BLPL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1294
	Pull	"R1"
Neil Turton's avatar
Neil Turton committed
1295 1296 1297 1298

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

1299 1300
        SUB     R13, R13, #8
        MOV     R9, R13
Kevin Bracey's avatar
Kevin Bracey committed
1301 1302 1303
	TEQ	R10, #RTCAddressPHI
        MOVEQ   R0, #1                  ; offset to start of time (varies)
        MOVNE   R0, #0
1304
        STRB    R0, [R9], #1
Kevin Bracey's avatar
Kevin Bracey committed
1305 1306
        MOVEQ   R0, R8                  ; centiseconds (not for Dallas parts)
        BLEQ    HTBS9
1307 1308 1309 1310 1311 1312
        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
1313 1314 1315 1316
        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
1317

Neil Turton's avatar
Neil Turton committed
1318
30
Neil Turton's avatar
Neil Turton committed
1319
	CMP	R2, #-1			; are we writing date ?
Kevin Bracey's avatar
Kevin Bracey committed
1320
	BEQ	%FT40
Neil Turton's avatar
Neil Turton committed
1321

1322 1323
        SUB     R13, R13, #8
        MOV     R9, R13
Kevin Bracey's avatar
Kevin Bracey committed
1324 1325 1326 1327 1328
	TEQ	R10, #RTCAddressPHI
	BNE     %FT35

	; Philips specific handling
        MOV     R0, #5                  ; offset 5
1329 1330 1331 1332 1333 1334 1335
        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
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
	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
1350

Neil Turton's avatar
Neil Turton committed
1351
40
Kevin Bracey's avatar
Kevin Bracey committed
1352 1353 1354
	Pull    "R0-R2"
	BL	RTCToRealTime		; update RAM copy
	Pull	"R4, R9-R10, PC"
Dan Ellis's avatar
Dan Ellis committed
1355

Kevin Bracey's avatar
Kevin Bracey committed
1356 1357 1358 1359 1360 1361 1362 1363
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"
1364
 ] ; RTCSupport :LOR: :LNOT: HAL
Neil Turton's avatar
Neil Turton committed
1365 1366 1367

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1368
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
1369
;
Neil Turton's avatar
Neil Turton committed
1370
; in:	-
Neil Turton's avatar
Neil Turton committed
1371
;
Neil Turton's avatar
Neil Turton committed
1372 1373
; out:	R0 = hours
;	R1 = minutes
1374 1375
;	R2 = days (1-based)
;	R3 = months (1-based)
Neil Turton's avatar
Neil Turton committed
1376 1377 1378 1379
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
1380
;	Note: For HAL RTCs, R0 will be negative on error. Other RTCs do not report errors and may just return garbage.
Neil Turton's avatar
Neil Turton committed
1381 1382

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
1383
	Push	"R4, R14"
Kevin Bracey's avatar
Kevin Bracey committed
1384 1385

        LDR	R14, =ZeroPage
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
        LDR	R2, [R14, #RTCFitted]
 [ HAL
	CMP	R2, #2048 ; IIC address or RTCDevice ptr?
	BLO	%FT49
	Push	"R12"
	MOV	R6, R2
	MOV	R0, R2
	SUB	R13, R13, #RTCTimeStruct_BCD_Size
	MOV	R1, R13
	ADRL	R2, HALRTC_IICOp
	MOV	LR, PC
	LDR	PC, [R0, #HALDevice_RTCReadTime]
1398 1399 1400 1401 1402 1403
	; If there was an error, exit with a negative value in R0
	CMP	R0, #RTCRetCode_OK
	MVNNE	R0, #0
	ADDNE	R13, R13, #RTCTimeStruct_BCD_Size
	Pull	"R12",NE
	Pull	"R4,PC",NE
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
	LDRB	R0, [R13, #RTCTimeStruct_BCD_Centiseconds]
	BL	BCDToHex
	MOV	R8, R0			; centiseconds
	LDRB	R0, [R13, #RTCTimeStruct_BCD_Seconds]
	BL	BCDToHex
	MOV	R7, R0			; seconds
	LDRB	R0, [R13, #RTCTimeStruct_BCD_Minutes]
	BL	BCDToHex
	MOV	R1, R0			; minutes
	LDRB	R0, [R13, #RTCTimeStruct_BCD_Hours]
	BL	BCDToHex
	MOV	R4, R0			; hours
	LDRB	R0, [R13, #RTCTimeStruct_BCD_DayOfMonth]
	BL	BCDToHex
	LDRB	R12, [R6, #HALDevice_RTCFormatFlags]
	MOV	R2, R0
	TST	R12, #RTCFormatFlags_BCD_1BasedDay
	ADDEQ	R2, R2, #1		; days
	LDRB	R0, [R13, #RTCTimeStruct_BCD_Month]
	BL	BCDToHex
	MOV	R3, R0
	TST	R12, #RTCFormatFlags_BCD_1BasedMonth
	ADDEQ	R3, R3, #1		; months
	LDRB	R0, [R13, #RTCTimeStruct_BCD_YearLO]
	BL	BCDToHex
	MOV	R5, R0			; year lo
	LDRB	R0, [R13, #RTCTimeStruct_BCD_YearHI]
	BL	BCDToHex
	; We're done with our stack data, remove it
	ADD	R13, R13, #RTCTimeStruct_BCD_Size
	MOV	R6, R0			; year hi
	; If the RTC can reliably store the year, we don't need to use the CMOS copy
	TST	R12, #RTCFormatFlags_BCD_NeedsYearHelp
	Pull	"R12"
	BEQ	DontReadTimeYear
	B	ReadTimeYear
49
 ] ; HAL
 [ RTCSupport :LOR: :LNOT: HAL
        SUB     R13, R13, #(12*2)+6+1+1
Kevin Bracey's avatar
Kevin Bracey committed
1444
        ORR     R14, R2, #1:SHL:29      ; retry
1445
        STR     R14, [R13, #8]          ; transfer 1 address
Kevin Bracey's avatar
Kevin Bracey committed
1446
        ADD     R0, R14, #1
1447
        STR     R0, [R13, #20]          ; transfer 2 address
Kevin Bracey's avatar
Kevin Bracey committed
1448 1449 1450
        TEQ	R2, #RTCAddressPHI
        MOVEQ   R0, #1			; PHI time starts at +1
        MOVNE   R0, #0			; DAL time starts at +0
1451
        STRB    R0, [R13, #0]
Kevin Bracey's avatar
Kevin Bracey committed
1452 1453
        STR     R13, [R13, #12]         ; transfer 1 dataptr
        MOV     R0, #1
1454 1455
        STR     R0, [R13, #16]          ; transfer 1 length
        ADD     R0, R13, #1
Kevin Bracey's avatar
Kevin Bracey committed
1456
        STR     R0, [R13, #24]          ; transfer 2 dataptr
1457 1458 1459 1460 1461 1462 1463
        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
1464 1465 1466 1467
	TEQ     R2, #RTCAddressPHI
	BNE	%FT50

	; Philips specific read
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487
        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
1488
	ADD     R13, R13, #(12*2)+6+1+1
Kevin Bracey's avatar
Kevin Bracey committed
1489
	B	ReadTimeYear
Neil Turton's avatar
Neil Turton committed
1490

Kevin Bracey's avatar
Kevin Bracey committed
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
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
1509 1510
	ADD     R13, R13, #(12*2)+6+1+1
 ] ; RTCSupport :LOR: :LNOT: HAL
Kevin Bracey's avatar
Kevin Bracey committed
1511 1512

ReadTimeYear
Neil Turton's avatar
Neil Turton committed
1513 1514 1515 1516 1517 1518
	MOV	R0, #YearCMOS
	BL	Read
	MOV	R5, R0			; year (lo)
	MOV	R0, #YearCMOS+1
	BL	Read
	MOV	R6, R0			; year (hi)
1519
DontReadTimeYear
Neil Turton's avatar
Neil Turton committed
1520
	MOV	R0, R4			; put hours in R0
Neil Turton's avatar
Neil Turton committed
1521

Kevin Bracey's avatar
Kevin Bracey committed
1522
	TEQ	R2, #0			; Ensure day/month are non-zero (LRust, fix RP-0370)
Neil Turton's avatar
Neil Turton committed
1523 1524 1525 1526
	MOVEQ	R2, #1			; No then force 1st
	TEQ	R3, #0			; Invalid month?
	MOVEQ	R3, #1			; Yes then force Jan
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1527

1528
 [ RTCSupport :LOR: :LNOT: HAL
Kevin Bracey's avatar
Kevin Bracey committed
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
; *****************************************************************************
;
;       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
1541
	ORR     R0, R0, #1:SHL:29
Kevin Bracey's avatar
Kevin Bracey committed
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553
	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
1554
	ORR     R0, R0, #1:SHL:29
Kevin Bracey's avatar
Kevin Bracey committed
1555 1556 1557 1558 1559 1560 1561
	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"
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
 ] ; RTCSupport :LOR: :LNOT: HAL


 [ HAL
; *****************************************************************************
;
;       HALRTC_IICOp - Wrapper for IIC_OpV to allow it to be called from HALDevice RTC drivers
;
;  in:  R0 = iic_transfer *
;	R1 = number of transfers
;	R2 = 'kernel workspace ptr' - currently unused
; out:  R0 = HAL_IICOp error code

HALRTC_IICOp
	Push	"R14"
	BL	IIC_OpV
	; Translate the RISC OS error code back into an IIC one we can pass to the driver
	LDRVS	R2, [R0]
	LDRVS	R1, =ErrorNumber_IIC_Busy
	MOV	R0, #5 ; EERROR
	TEQ	R2, R1 ; Won't modify V
	MOVEQ	R0, #3 ; EBUSY
	LDRVS	R1, =ErrorNumber_IIC_NoAcknowledge
	TEQ	R2, R1
	MOVEQ	R0, #2 ; ENOACK
	MOVVC	R0, #0 ; ECOMPLETED
	Pull	"PC"
 ]

Kevin Bracey's avatar
Kevin Bracey committed
1591

Neil Turton's avatar
Neil Turton committed
1592 1593
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1594
;	InitCMOSCache - Initialise cache of CMOS RAM
Dan Ellis's avatar
Dan Ellis committed
1595 1596 1597
;  in: -
;
;  out: R0 = 0 for failure
Neil Turton's avatar
Neil Turton committed
1598

1599
InitCMOSCache	Entry "r1-r6, sb,r12"
Neil Turton's avatar
Neil Turton committed
1600 1601
    [	E2ROMSupport

Kevin Bracey's avatar
Kevin Bracey committed
1602 1603 1604 1605
	; 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
1606

Kevin Bracey's avatar
Kevin Bracey committed
1607 1608 1609
	; Have we got an RTC ?
	LDR 	R2, =ZeroPage
	MOV	R4, #0
1610
     [  RTCSupport
1611
	MOV	R0, #RTCAddressDAL
Kevin Bracey's avatar
Kevin Bracey committed
1612 1613
	BL	DummyAccess
	BVC	%FT13
1614
	MOV	R0, #RTCAddressPHI
Kevin Bracey's avatar
Kevin Bracey committed
1615
	BL	DummyAccess
1616
	STRVS   R4, [R2, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
1617
13
1618
	STRVC   R0, [R2, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
1619
	BLVC    InitRTC
1620
     |
1621
        STR     R4, [R2, #RTCFitted]
1622
     ]
Neil Turton's avatar
Neil Turton committed
1623

Dan Ellis's avatar
Dan Ellis committed
1624 1625 1626
 [ HAL
        AddressHAL
    	CallHAL	HAL_NVMemoryType
Ben Avison's avatar
Ben Avison committed
1627
    	MOV 	R5, R0
Dan Ellis's avatar
Dan Ellis committed
1628
    	ANDS 	R0, R0, #NVMemoryFlag_Provision
Kevin Bracey's avatar
Kevin Bracey committed
1629
        BEQ     InitCMOSCache_NoCMOS
Dan Ellis's avatar
Dan Ellis committed
1630 1631

    	; If it's only a maybe, then we probe
1632
    	TEQ 	R0, #NVMemoryFlag_MaybeIIC
Dan Ellis's avatar
Dan Ellis committed
1633 1634 1635 1636 1637 1638 1639 1640
    	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]

1641 1642 1643 1644 1645 1646 1647 1648 1649
        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
1650 1651 1652 1653 1654 1655 1656 1657 1658
        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
1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671
    	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
1672
        AND	R0, R5, #NVMemoryFlag_Provision
Dan Ellis's avatar
Dan Ellis committed
1673 1674 1675 1676 1677 1678 1679 1680 1681
    	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
1682
    	MOVNE	R0, #0			; Failure exit condition
Dan Ellis's avatar
Dan Ellis committed
1683 1684 1685
    	EXIT
03
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1686 1687 1688

;	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
1689

Robert Catherall's avatar
Robert Catherall committed
1690
        MOV     R3, #10         ; assume 100kHz to start with
Kevin Bracey's avatar
Kevin Bracey committed
1691
        MOV     R5, #4          ; assume 16 byte page size to start with
1692
        MOV     R6, #0          ; assume not protected
Kevin Bracey's avatar
Kevin Bracey committed
1693

Kevin Bracey's avatar
Kevin Bracey committed
1694
; Have we got a 2K device ?
Kevin Bracey's avatar
Kevin Bracey committed
1695 1696 1697 1698 1699 1700
        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
1701

1702
; Have we got a 16K device ?
Kevin Bracey's avatar
Kevin Bracey committed
1703 1704 1705 1706 1707 1708
        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)
1709 1710
        BVC     %FT5

1711 1712 1713 1714 1715 1716 1717 1718 1719 1720
; 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

1721 1722 1723 1724 1725
; Have we got an 8K device?
        MOV     r1, #E2ROMAddress8K
	MOV	r0, #E2ROMAddress8K
	BL	DummyAccess
	MOVVC	R4, #32
1726 1727 1728 1729 1730 1731 1732 1733 1734
        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
1735
        MOVVC   R6, #24         ; Only bottom 6K writable
1736 1737
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
Robert Catherall's avatar
Robert Catherall committed
1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
        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
1748
    	BVC 	%FT5
Robert Catherall's avatar
Robert Catherall committed
1749

Kevin Bracey's avatar
Kevin Bracey committed
1750 1751 1752
; Any storeage in the Philips RTC? (Dallas capacity is tiny,ignored)
        MOV     R1, #RTCAddressPHI
        MOV     R0, #RTCAddressPHI
Dan Ellis's avatar
Dan Ellis committed
1753 1754
    	BL  	DummyAccess
        MOV     R5, #8          ; 256 byte page size for CMOS
1755
        MOVVC   R4, #1
Dan Ellis's avatar
Dan Ellis committed
1756 1757 1758
    	BVC 	%FT5

; We ain't got anything!
Kevin Bracey's avatar
Kevin Bracey committed
1759 1760 1761 1762 1763 1764 1765
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
1766
    	MOV 	R0, #0		; Exit failure
Dan Ellis's avatar
Dan Ellis committed
1767
    	EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1768 1769

5
Neil Turton's avatar
Neil Turton committed
1770
	; Set the NVRam count
Kevin Bracey's avatar
Kevin Bracey committed
1771 1772 1773
	STRB    R1, [R2, #NVRamBase]
	STRB	R4, [R2, #NVRamSize]
        STRB    R5, [R2, #NVRamPageSize]
1774 1775 1776
        TEQ     R6, #0
        MOVEQ   R6, R4
        STRB    R6, [R2, #NVRamWriteSize]
Robert Catherall's avatar
Robert Catherall committed
1777 1778 1779

        CMP     R3, #I2Cticks   ; clamp speed to maximum bus speed
        MOVLO   R3, #I2Cticks
Kevin Bracey's avatar
Kevin Bracey committed
1780
        STRB    R3, [R2, #NVRamSpeed]
Dan Ellis's avatar
Dan Ellis committed
1781 1782
06
	; Initialise the cache
Kevin Bracey's avatar
Kevin Bracey committed
1783
	LDR	R3, =CMOSRAMCache
Neil Turton's avatar
Neil Turton committed
1784

Kevin Bracey's avatar
Kevin Bracey committed
1785 1786 1787 1788 1789 1790 1791 1792 1793
        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
1794
    |
Kevin Bracey's avatar
Kevin Bracey committed
1795 1796 1797 1798 1799
    	; 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
1800
    ]
1801 1802 1803

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

1806 1807 1808 1809 1810
        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
1811
        TST     R1, #&100               ; 2-byte address?
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830
        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
1831 1832 1833

   [ E2ROMSupport
ReadOTPArea Entry
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
        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
1852
   ]
Neil Turton's avatar
Neil Turton committed
1853

Neil Turton's avatar
Neil Turton committed
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
; *****************************************************************************
;
;	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
1866
DummyAccess
1867

Kevin Bracey's avatar
Kevin Bracey committed
1868 1869 1870 1871 1872 1873 1874 1875 1876
 [ {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"
1877 1878 1879
        MOV     R1, #0
        MOV     R2, #0
        BL      IIC_Op
Kevin Bracey's avatar
Kevin Bracey committed
1880
 ]
Neil Turton's avatar
Neil Turton committed
1881 1882 1883 1884

	EXIT				; Exit with V set appropriately
  ]

Kevin Bracey's avatar
Kevin Bracey committed
1885 1886 1887 1888 1889 1890 1891
; *****************************************************************************
;
;       SWI OS_NVMemory
;
; in:   R0 = reason code
;

1892
NVMemorySWI     Entry
Kevin Bracey's avatar
Kevin Bracey committed
1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914
        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
1915
        RETURNVS
Kevin Bracey's avatar
Kevin Bracey committed
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930

; -----------------------------------------------------------------------------
; 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
1931
        MOV     PC, LR
Kevin Bracey's avatar
Kevin Bracey committed
1932 1933 1934 1935 1936 1937 1938 1939 1940 1941

; -----------------------------------------------------------------------------
; OS_NVMemory 1 - read a byte
;
; in:   R0 = 1
;       R1 = location
;
; out:  R2 = value
;
NVMemory_Read
1942 1943
        Entry   "R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1944
        BIC     R0, R4, #I32_bit
1945
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1946 1947 1948 1949 1950
        MOV     R0, R1
        BL      ReadWithError
        MOVVC   R2, R0
        MOVVC   R0, #1          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1951
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965
        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
        ]
1966 1967
        Entry   "R1,R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1968
        BIC     R0, R4, #I32_bit
1969
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1970 1971 1972 1973 1974
        MOV     R0, R1
        MOV     R1, R2
        BL      WriteWithError
        MOVVC   R0, #2          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1975
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 3 - read a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_ReadBlock
1987
        Entry   "R1-R4"
Kevin Bracey's avatar
Kevin Bracey committed
1988
        MOV     R4, PC
1989
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1990
        BIC     R0, R4, #I32_bit
1991
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1992 1993 1994 1995 1996 1997
        MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      ReadBlock
        MOVVC   R0, #3          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1998
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 4 - write a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_WriteBlock ROUT
2010 2011
        Entry   "R1-R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
2012
        BIC     R0, R4, #I32_bit
2013
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
        [ 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
2028
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
2029 2030
        EXIT

Neil Turton's avatar
Neil Turton committed
2031
	END