i2cutils 49.9 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 32 33
; ***********************************
; ***    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.
; amg 7/12/96 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 40 41 42

PhysChecksum	*	(((CheckSumCMOS + &30) :MOD: &F0) + &10)

; Device addresses
Kevin Bracey's avatar
Kevin Bracey committed
43 44 45 46
RTCAddress		*	&a0     ; traditional RTC / 240 byte CMOS
E2ROMAddress		*	&a8     ; 24C08 device - 512 byte or 1K
E2ROMAddress2K		*	&e0     ; 24C174 device - 2K
E2ROMAddress2K_OTP	*	&60     ; 24C174 device - OTP section
47 48
E2ROMAddress4K          *       &a4     ; 24C32 device - 4K (top 1K protectable)
E2ROMAddress8K          *       &a2     ; 24C64 device - 8K (top 2K protectable)
Kevin Bracey's avatar
Kevin Bracey committed
49
E2ROMAddress16K         *       &a8     ; 24C128 device - 16K
Robert Catherall's avatar
Robert Catherall committed
50 51
E2ROMAddress32K         *       &a6     ; 24CS256 device - 32K (top 2K possibly OTP)

Dan Ellis's avatar
Dan Ellis committed
52

Neil Turton's avatar
Neil Turton committed
53 54
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
55
;	HexToBCD - Convert byte in hex to BCD
Neil Turton's avatar
Neil Turton committed
56
;
Neil Turton's avatar
Neil Turton committed
57
; in:	R0 = byte in hex
Neil Turton's avatar
Neil Turton committed
58
;
Neil Turton's avatar
Neil Turton committed
59 60
; 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
61 62 63
;

HexToBCD ROUT
Neil Turton's avatar
Neil Turton committed
64 65 66 67 68
	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
69 70 71

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

BCDToHex ROUT
Neil Turton's avatar
Neil Turton committed
81 82 83 84 85
	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
86

87 88

; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
89

90
HTBS9   ROUT
91
        Push    R14
92 93 94
        BL      HexToBCD
        STRB    R0, [R9], #1
        Pull    PC
Neil Turton's avatar
Neil Turton committed
95 96 97

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

Kevin Bracey's avatar
Kevin Bracey committed
106 107 108 109 110 111 112 113 114
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
115 116
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
117
 ]
Kevin Bracey's avatar
Kevin Bracey committed
118
        Pull    "R1-R4,PC"
Kevin Bracey's avatar
Kevin Bracey committed
119 120 121

        MakeErrorBlock CoreNotWriteable

Robert Catherall's avatar
Robert Catherall committed
122 123 124 125 126 127 128 129 130 131 132
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
133
Write
Neil Turton's avatar
Neil Turton committed
134 135 136
	Push	"R0-R4, R14"
	BL	MangleCMOSAddress
	Pull	"R0-R4, PC", CS		; if invalid, then exit
Kevin Bracey's avatar
Kevin Bracey committed
137 138 139 140 141
05
  [ E2ROMSupport
        CMP     r0, #&10
        Pull    "R0-R4, PC", CC         ; don't write to OTP section
  ]
Neil Turton's avatar
Neil Turton committed
142

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

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

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

Neil Turton's avatar
Neil Turton committed
164 165 166 167
	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
168
10
Kevin Bracey's avatar
Kevin Bracey committed
169 170 171
	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
172
	STRB	R3, [R1, R2]		; real hardware as well
Kevin Bracey's avatar
Kevin Bracey committed
173
15
Dan Ellis's avatar
Dan Ellis committed
174 175

  [ HAL
176
    	Push	"R2,R3,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
177 178 179 180 181 182
    	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.
183
    	Pull 	"R2,R3,sb,R12", EQ
Dan Ellis's avatar
Dan Ellis committed
184 185 186 187 188 189
	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.
190
        Pull    "R0"
191
        STRB    R3, [sp, #-4]!
192 193 194
    	MOV 	R1, sp
    	MOV 	R2, #1
    	CallHAL	HAL_NVMemoryWrite
195 196 197 198 199
        TST     R4, #&1000000
        BNE     %FT18
        LDR     R1, =CMOSRAMCache
        STRB    R4, [R1, #PhysChecksum]
        STRB    R4, [sp]
200
        MOV     R0, #PhysChecksum
Dan Ellis's avatar
Dan Ellis committed
201 202 203
    	MOV 	R1, sp
    	MOV 	R2, #1
    	CallHAL	HAL_NVMemoryWrite
204 205 206
18
    	ADD     sp, sp, #4
    	Pull	"R3,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
207 208
    	Pull	"R0-R4,PC"
20
209
        Pull    "R2,R3,sb,R12"
Dan Ellis's avatar
Dan Ellis committed
210 211 212
  ]


Neil Turton's avatar
Neil Turton committed
213 214 215 216 217 218
 [ E2ROMSupport
	MOV	R0, R2
	BL	GetI2CAddress		; convert to device address + offset
	MOV	R2, R0			; save the offset
 |
	MOV	R1, #RTCAddress
Neil Turton's avatar
Neil Turton committed
219 220 221
 ]


222 223 224 225 226 227 228 229 230 231 232 233 234
        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
235

Neil Turton's avatar
Neil Turton committed
236 237 238 239 240 241 242 243
	[ 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
244

Kevin Bracey's avatar
Kevin Bracey committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
; *****************************************************************************
;
;       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
261
        LDRB    R4, [R14, #NVRamWriteSize]
Kevin Bracey's avatar
Kevin Bracey committed
262
        LDRB	R14, [R14, #NVRamSize]
263
        MOV     R4, R4, LSL #8
Kevin Bracey's avatar
Kevin Bracey committed
264 265 266
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
267
        MOV     R4, R14
Kevin Bracey's avatar
Kevin Bracey committed
268 269 270 271 272 273 274 275 276 277
  ]

        CMP     R0, R14
        BHS     %FT90

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

278 279 280 281 282 283
        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
284 285 286 287 288 289 290 291 292 293 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
        TEQ     R2, #0
        BEQ     %FT80

        CMP     R0, #CheckSumCMOS       ; are we going to write the checksum byte?
        BHI     %FT03
        CMP     R3, #CheckSumCMOS
        BHS     %FT05

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
326 327
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
328
 ]
Kevin Bracey's avatar
Kevin Bracey committed
329
        Pull    "R1-R4,PC"
Kevin Bracey's avatar
Kevin Bracey committed
330 331 332 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

; *****************************************************************************
;
;       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
419
  [ HAL
420
    	Push	"sb, R12"
Dan Ellis's avatar
Dan Ellis committed
421 422 423 424 425 426 427
    	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.
428
    	Pull 	"sb,R12", EQ
Dan Ellis's avatar
Dan Ellis committed
429 430 431 432 433 434 435 436 437 438
    	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
439 440 441
        MOV     R5, R0
    	Pull	"sb,R12"

Dan Ellis's avatar
Dan Ellis committed
442
    	Pull	"R0-R2"
443 444 445 446 447 448

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

16      SUBS    R5, R5, #1              ; update checksum
        LDRCS   R14, [R1], #1
449
        ADDCS   R6, R6, R14
450
        BCS     %BT16
451
        MOV     R4, R6
452

Dan Ellis's avatar
Dan Ellis committed
453 454 455
    	Pull	"R3,R5-R6,PC"

17
456
    	Pull	"sb,R12"
Dan Ellis's avatar
Dan Ellis committed
457 458
  ]

Kevin Bracey's avatar
Kevin Bracey committed
459 460 461 462 463 464
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

465 466 467
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
468
        TST     R1, #&100               ; 2-byte address?
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
        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
485 486 487
        SUB     R5, R3, R0              ; R5 = bytes being written
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
488 489 490 491 492 493 494 495 496 497
        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
498 499 500
20
        LDRB    R0, [R1], #1
        SUBS    R5, R5, #1
501
        ADD     R6, R6, R0              ; update checksum counter
Kevin Bracey's avatar
Kevin Bracey committed
502
        BNE     %BT20
Kevin Bracey's avatar
Kevin Bracey committed
503
                                        ; V clear
Kevin Bracey's avatar
Kevin Bracey committed
504 505
        MOV     R4, R6

Kevin Bracey's avatar
Kevin Bracey committed
506
	Pull	"R0,R2,R3,R5,R6,PC"
Kevin Bracey's avatar
Kevin Bracey committed
507

Neil Turton's avatar
Neil Turton committed
508 509
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
510 511
;	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
512
;       ReadWithError - Read a byte of CMOS RAM specified by logical address, giving error if out of range
Neil Turton's avatar
Neil Turton committed
513
;
Neil Turton's avatar
Neil Turton committed
514
; in:	R0 = address in CMOS RAM
Neil Turton's avatar
Neil Turton committed
515
;
Kevin Bracey's avatar
Kevin Bracey committed
516
; out:	R0 = data (illegal address return 0, or error for ReadWithError)
Neil Turton's avatar
Neil Turton committed
517
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
518 519 520
;

ReadStraight ROUT
Neil Turton's avatar
Neil Turton committed
521 522
	Push	"R1,R2,R14"
	B	%FT10
Neil Turton's avatar
Neil Turton committed
523

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

        MakeErrorBlock CoreNotReadable

Neil Turton's avatar
Neil Turton committed
538
Read
Neil Turton's avatar
Neil Turton committed
539 540 541 542
	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
543
10
Neil Turton's avatar
Neil Turton committed
544 545
	TEQ	R0, #&40		; is it Econet station number
	BEQ	%FT15	 		; if so then don't use cache
Kevin Bracey's avatar
Kevin Bracey committed
546 547 548 549 550 551 552 553 554 555 556
        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
557 558 559
	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
560 561 562
15

; else drop thru into real CMOS reading code
Dan Ellis's avatar
Dan Ellis committed
563 564

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

20
591
        Pull    "R3, sb,R12"
Neil Turton's avatar
Neil Turton committed
592
  ]
Neil Turton's avatar
Neil Turton committed
593

Neil Turton's avatar
Neil Turton committed
594 595 596 597 598
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]
Neil Turton's avatar
Neil Turton committed
599

600 601 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
        BL      IIC_OpV
        LDRB    R0, [R13, #3]
        ADD     R13, R13, #2*12+4
Neil Turton's avatar
Neil Turton committed
621

Neil Turton's avatar
Neil Turton committed
622
	Pull	"R1,R2,PC"
Neil Turton's avatar
Neil Turton committed
623

Kevin Bracey's avatar
Kevin Bracey committed
624 625 626 627 628 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

; *****************************************************************************
;
;       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
670 671
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
672
 ]
Kevin Bracey's avatar
Kevin Bracey committed
673
        Pull    "R1-R3,PC"
Kevin Bracey's avatar
Kevin Bracey committed
674 675 676 677 678 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

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

17
    	Pull	"sb"
  ]

Kevin Bracey's avatar
Kevin Bracey committed
773 774 775 776 777 778 779
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]


780 781 782
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
783
        TST     R1, #&100               ; 2-byte address?
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
        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
800 801 802
        SUB     R5, R3, R0              ; R5 = bytes being read
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
803 804 805 806 807 808 809 810 811 812 813 814 815
        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
816

Kevin Bracey's avatar
Kevin Bracey committed
817
	Pull	"R0,R2,R3-R5,PC"
Kevin Bracey's avatar
Kevin Bracey committed
818 819 820 821 822 823 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

; *****************************************************************************
;
;       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"
916
        ADD     R0, R0, R4              ; R0 = physical start address
917
  [ HAL
918 919
        ADD     R3, R3, R4              ; R3 = physical end address
    	Push	"sb,R12"
920 921
    	MOV 	R5, R0	    	    	; save address
    	AddressHAL
922
    	Push	"R1-R3"
923
    	CallHAL	HAL_NVMemoryType
924 925 926 927
    	Pull	"R1-R3"
    	AND 	R4, R0, #NVMemoryFlag_Provision
    	MOV 	R0, R5	    	    	; restore address
    	TEQ 	R4, #NVMemoryFlag_None
928

929 930 931 932 933 934 935
        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]
936 937

    	; If there's no NVmemory, tough - we just return.
938
    	Pull 	"sb,R12", EQ
939 940
	Pull	"R0-R5,PC", EQ

941
    	TEQ 	R4, #NVMemoryFlag_HAL
942 943 944 945
    	BNE 	%FT17	    	    	; do IIC things.

        Push    "R6"
        MOV     R4, #0
946
        ADD     R6, R5, R14
947 948 949 950 951 952 953 954 955 956 957 958
        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
959
        Pull    "R6,sb,R12"
960 961 962 963
        Pull    "R0-R2"
        ADD     R1,R1,R4
        Pull    "R3-R5,PC"
17
964
        Pull    "sb,R12"
965
  ]
Kevin Bracey's avatar
Kevin Bracey committed
966 967 968 969 970 971
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

972 973 974
        MOV     R2, R0                  ; save the offset
        SUB     R13, R13, #12*2+4
        MOV     R14, R13
Kevin Bracey's avatar
Kevin Bracey committed
975
        TST     R1, #&100               ; 2-byte address?
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
        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
993 994 995
        SUB     R5, R3, R0              ; R5 = bytes being read
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
996 997
        STMIB   R14, {R0,R2}
        MOV     R4, R1                  ; remember checksum
Kevin Bracey's avatar
Kevin Bracey committed
998

999 1000 1001 1002 1003 1004 1005 1006
        STR     R5, [R13, #24]          ; transfer 2 length
        ADD     R0, R13, #4
        MOV     R1, #2
        BL      IIC_OpV

        LDR     R1, [R13, #20]          ; read back checksum
        ADD     R1, R1, R4              ; update checksum
        ADD     R13, R13, #12*2+4+4
Kevin Bracey's avatar
Kevin Bracey committed
1007 1008 1009

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

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

Kevin Bracey's avatar
Kevin Bracey committed
1037 1038
; address is < end address -> is valid
	MOV	R1, #0
Neil Turton's avatar
Neil Turton committed
1039
	LDRB	R1, [R1, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
1040 1041 1042 1043 1044 1045 1046
	TEQ	R1, #0
	MOVNE	R1, #RTCAddress
	LDREQB  R1, [R1, #NVRamBase]

        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
1047

Kevin Bracey's avatar
Kevin Bracey committed
1048 1049 1050 1051
	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
1052 1053
        CLC
	Pull	"PC"           		; indicate valid
Kevin Bracey's avatar
Kevin Bracey committed
1054

Neil Turton's avatar
Neil Turton committed
1055
  ]
Neil Turton's avatar
Neil Turton committed
1056 1057 1058


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
1059 1060 1061 1062 1063
;
;	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
1064
; in:	R0 = logical address (&00...)
Neil Turton's avatar
Neil Turton committed
1065
;
Kevin Bracey's avatar
Kevin Bracey committed
1066 1067
; out:	C=0 => valid logical address
;	 R0 = physical address (&40..&FF,&10..&3F,&00..0F,&100..)
Neil Turton's avatar
Neil Turton committed
1068
;
Kevin Bracey's avatar
Kevin Bracey committed
1069
;	C=1 => invalid logical address
Neil Turton's avatar
Neil Turton committed
1070 1071
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
1072

Neil Turton's avatar
Neil Turton committed
1073
MangleCMOSAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1074 1075 1076 1077 1078 1079 1080
 [ 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
1081
        MOVCS   PC, R14 		;    invalid (exit C set)
Kevin Bracey's avatar
Kevin Bracey committed
1082 1083

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

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1107 1108
;	ValChecksum - test to see if the CMOS checksum is OK
;
Kevin Bracey's avatar
Kevin Bracey committed
1109 1110 1111 1112 1113
;       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
1114
;
Neil Turton's avatar
Neil Turton committed
1115
; in:	none
Neil Turton's avatar
Neil Turton committed
1116
;
Neil Turton's avatar
Neil Turton committed
1117 1118 1119
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1120 1121
;

Neil Turton's avatar
Neil Turton committed
1122
  [ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1123

1124
ValChecksum	Entry "R1-R2"
Neil Turton's avatar
Neil Turton committed
1125

Kevin Bracey's avatar
Kevin Bracey committed
1126 1127
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1128
   [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1129 1130 1131
	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
1132 1133 1134
   |
	MOV	R2, #240
   ]
Kevin Bracey's avatar
Kevin Bracey committed
1135
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1136 1137

;
Kevin Bracey's avatar
Kevin Bracey committed
1138
; R1 contains the actual checksum. Compare it with the recorded checksum
Neil Turton's avatar
Neil Turton committed
1139
;
Kevin Bracey's avatar
Kevin Bracey committed
1140 1141 1142
40
	MOV	R0, #CheckSumCMOS
	BL	Read
Neil Turton's avatar
Neil Turton committed
1143
	AND	R2, R0, #&FF		; value from checksum location
Kevin Bracey's avatar
Kevin Bracey committed
1144
	AND	R0, R1, #&FF		; calculated value into R0
Neil Turton's avatar
Neil Turton committed
1145
	CMPS	R0, R2
Neil Turton's avatar
Neil Turton committed
1146

Neil Turton's avatar
Neil Turton committed
1147 1148
	EXIT
  ]
Neil Turton's avatar
Neil Turton committed
1149 1150 1151

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1152
;	MakeChecksum - calculate and write a correct checksum
Neil Turton's avatar
Neil Turton committed
1153
;
Neil Turton's avatar
Neil Turton committed
1154
; in:	none
Neil Turton's avatar
Neil Turton committed
1155
;
Neil Turton's avatar
Neil Turton committed
1156 1157
; out:	R0 = calculated checksum
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1158 1159
;

Neil Turton's avatar
Neil Turton committed
1160
	[ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1161

Neil Turton's avatar
Neil Turton committed
1162
MakeChecksum	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1163 1164 1165
	Push	"R1-R2,R14"
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1166
  [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1167 1168 1169
	MOV	R2, #0
	LDRB	R2, [R2, #NVRamSize]
	MOV	R2, R2, LSL #8
Stewart Brodie's avatar
Stewart Brodie committed
1170 1171 1172
  |
	MOV	R2, #240
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1173
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1174 1175
	MOV	R0, #CheckSumCMOS
	BL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1176
	Pull	"R1-R2,PC"
Neil Turton's avatar
Neil Turton committed
1177
	]
Neil Turton's avatar
Neil Turton committed
1178

Kevin Bracey's avatar
Kevin Bracey committed
1179 1180
        LTORG

Neil Turton's avatar
Neil Turton committed
1181 1182
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1183
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
1184
;
Neil Turton's avatar
Neil Turton committed
1185 1186 1187 1188 1189 1190 1191 1192 1193
; 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
1194
;
Neil Turton's avatar
Neil Turton committed
1195
;	Any of the above, if -1, will not be written to
Neil Turton's avatar
Neil Turton committed
1196 1197 1198
;

SetTime ROUT
1199
	Push	"R4, R9, R14"		; save registers
Neil Turton's avatar
Neil Turton committed
1200

Stewart Brodie's avatar
Stewart Brodie committed
1201
 [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1202 1203 1204 1205 1206 1207 1208 1209 1210
	MOV	R14, #0
	LDRB	R14, [R14, #RTCFitted]

        TEQ     R14, #0
        BNE     %FT20

; no RTC - just set soft copy

        BL      RegToRealTime
Dan Ellis's avatar
Dan Ellis committed
1211

1212
        Pull    "R4, R9, PC"
Stewart Brodie's avatar
Stewart Brodie committed
1213
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1214
20
Neil Turton's avatar
Neil Turton committed
1215 1216
; write year to CMOS RAM

Neil Turton's avatar
Neil Turton committed
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
	MOV	R4, R0			; save hours in R4

	Push	"R1"
	MOVS	R1, R5
	MOVPL	R0, #YearCMOS
	BLPL	Write
	MOVS	R1, R6
	MOVPL	R0, #YearCMOS+1
	BLPL	Write

	CMP	R4, #-1			; are we writing time ?
	Pull	"R1",EQ			; [no, then skip]
	BEQ	%FT30

1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
	Pull	"R1"

        SUB     R13, R13, #8
        MOV     R9, R13
        MOV     R0, #&01                ; offset 1
        STRB    R0, [R9], #1
        MOV     R0, R8                  ; centiseconds
        BL      HTBS9
        MOV     R0, R7                  ; seconds
        BL      HTBS9
        MOV     R0, R1                  ; minutes
        BL      HTBS9
        MOV     R0, R4                  ; hours
        BL      HTBS9
        Push    "R0-R2"
Neil Turton's avatar
Neil Turton committed
1246
    [	E2ROMSupport
1247
	MOV	R0, #&01		; start at address 1
Neil Turton's avatar
Neil Turton committed
1248 1249 1250 1251 1252
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
1253 1254 1255 1256 1257 1258
        ORR     R0, R0, #1:SHL:29       ; retry
        MOV     R1, R13
        SUB     R2, R9, R13
        BL      IIC_Op
        Pull    "R0-R2"
        ADD     R13, R13, #8
Neil Turton's avatar
Neil Turton committed
1259

Neil Turton's avatar
Neil Turton committed
1260
30
Neil Turton's avatar
Neil Turton committed
1261 1262 1263
	CMP	R2, #-1			; are we writing date ?
	BEQ	%FT40			; [no, then skip]

1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
        SUB     R13, R13, #8
        MOV     R9, R13
        MOV     R0, #&05                ; offset 5
        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
        Push    "R0-R2"
Neil Turton's avatar
Neil Turton committed
1275
    [	E2ROMSupport
1276
	MOV	R0, #&05		; start at address 5
Neil Turton's avatar
Neil Turton committed
1277 1278 1279 1280 1281
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
1282 1283 1284 1285 1286
        ORR     R0, R0, #1:SHL:29       ; retry
        MOV     R1, R13
        SUB     R2, R9, R13
        BL      IIC_Op
        Pull    "R0-R2"
Neil Turton's avatar
Neil Turton committed
1287

Neil Turton's avatar
Neil Turton committed
1288 1289 1290
40
	MOV	R0, R4			; put hours back in R0
	BL	RTCToRealTime
Dan Ellis's avatar
Dan Ellis committed
1291

1292
	Pull	"R4, R9, PC"
Neil Turton's avatar
Neil Turton committed
1293 1294 1295

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1296
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
1297
;
Neil Turton's avatar
Neil Turton committed
1298
; in:	-
Neil Turton's avatar
Neil Turton committed
1299
;
Neil Turton's avatar
Neil Turton committed
1300 1301 1302 1303 1304 1305 1306 1307
; 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
1308 1309 1310
;

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
1311
	Push	"R4, R14"
1312
        SUB     R13, R13, #12*2+8
Neil Turton's avatar
Neil Turton committed
1313
    [	E2ROMSupport
1314
	MOV	R0, #&01		; start at address 1
Neil Turton's avatar
Neil Turton committed
1315 1316 1317 1318 1319
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
        ORR     R14, R0, #1:SHL:29      ; retry
        STR     R14, [R13, #8]          ; transfer 1 address
        ADD     R0, R0, #1
        STR     R0, [R13, #20]          ; transfer 2 address
        MOV     R0, #&01                ; offset 1
        STRB    R0, [R13, #0]
        STR     R13, [R13, #12]         ; transfer 1 data
        STR     R0, [R13, #16]          ; transfer 1 length
        ADD     R0, R13, #1
        STR     R0, [R13, #24]          ; transfer 2 data
        MOV     R0, #6
        STR     R0, [R13, #28]          ; transfer 2 length

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

        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
        ADD     R13, R13, #12*2+8
Neil Turton's avatar
Neil Turton committed
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367

	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
1368 1369

; Ensure day/month are non-zero, fixes RTCToRealTime
Neil Turton's avatar
Neil Turton committed
1370 1371 1372 1373 1374
 [ {TRUE}				; LRust, fix RP-0370
	TEQ	R2, #0			; Valid day?
	MOVEQ	R2, #1			; No then force 1st
	TEQ	R3, #0			; Invalid month?
	MOVEQ	R3, #1			; Yes then force Jan
Neil Turton's avatar
Neil Turton committed
1375
 ]
Neil Turton's avatar
Neil Turton committed
1376
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1377 1378 1379

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1380
;	InitCMOSCache - Initialise cache of CMOS RAM
Dan Ellis's avatar
Dan Ellis committed
1381 1382 1383
;  in: -
;
;  out: R0 = 0 for failure
Neil Turton's avatar
Neil Turton committed
1384

1385
InitCMOSCache	Entry "r1-r6, sb,r12"
Neil Turton's avatar
Neil Turton committed
1386 1387
    [	E2ROMSupport

Kevin Bracey's avatar
Kevin Bracey committed
1388 1389
; Need to set the slowest speed so we can probe

Dan Ellis's avatar
Dan Ellis committed
1390
        LDR     R4, =ZeroPage
Kevin Bracey's avatar
Kevin Bracey committed
1391
        MOV     R3, #10         ; Default speed setting (5s delays)
Dan Ellis's avatar
Dan Ellis committed
1392
        STRB    R3, [R4, #NVRamSpeed]
Kevin Bracey's avatar
Kevin Bracey committed
1393 1394

;	First determine what hardware we've got fitted, R4 holds the number of
Neil Turton's avatar
Neil Turton committed
1395 1396
;	256 byte blocks that we've found

Dan Ellis's avatar
Dan Ellis committed
1397 1398 1399 1400
 [ HAL
        AddressHAL
    	CallHAL	HAL_NVMemoryType
    	ANDS 	R0, R0, #NVMemoryFlag_Provision
Kevin Bracey's avatar
Kevin Bracey committed
1401
        BEQ     InitCMOSCache_NoCMOS
Dan Ellis's avatar
Dan Ellis committed
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
    	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]

1414 1415 1416 1417 1418 1419 1420 1421 1422
        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
Dan Ellis's avatar
Dan Ellis committed
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
    	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
    	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
    	MOVNE	R0, #0	    	    	; Failure exit condition
    	EXIT
03
 ]
Neil Turton's avatar
Neil Turton committed
1449 1450
	; Have we got an RTC ?
	MOV	R0, #RTCAddress
Dan Ellis's avatar
Dan Ellis committed
1451
    	LDR 	R2, =ZeroPage
Neil Turton's avatar
Neil Turton committed
1452
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1453 1454 1455
	MOVVS	R4, #0
	MOVVC	R4, #1
	STRB	R4, [R2, #RTCFitted]
Dan Ellis's avatar
Dan Ellis committed
1456

Robert Catherall's avatar
Robert Catherall committed
1457
        MOV     R3, #10         ; assume 100kHz to start with
Kevin Bracey's avatar
Kevin Bracey committed
1458
        MOV     R5, #4          ; assume 16 byte page size to start with
1459
        MOV     R6, #0          ; assume not protected
Kevin Bracey's avatar
Kevin Bracey committed
1460 1461 1462 1463 1464 1465 1466 1467

; Have we got a 2K E ?
        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
1468 1469

; Have we got a 1K E ?
Kevin Bracey's avatar
Kevin Bracey committed
1470
        MOV     r1, #E2ROMAddress
Neil Turton's avatar
Neil Turton committed
1471 1472
	MOV	r0, #(E2ROMAddress+6)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1473
	MOVVC	R4, #4
Neil Turton's avatar
Neil Turton committed
1474 1475 1476 1477 1478
	BVC	%FT5

; Have we got 512 bytes of E ?
	MOV	r0, #(E2ROMAddress+2)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1479
	MOVVC	R4, #2
Neil Turton's avatar
Neil Turton committed
1480 1481
	BVC	%FT5

Kevin Bracey's avatar
Kevin Bracey committed
1482 1483 1484
; Have we got a 16K device ? (Note that this probe would make a 24C08 device respond -
; but if we've gotten this far it would have to be a < 512 byte version; we've never
; used such a device).
Neil Turton's avatar
Neil Turton committed
1485

Kevin Bracey's avatar
Kevin Bracey committed
1486 1487 1488 1489 1490 1491
        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)
1492 1493
        BVC     %FT5

1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
; 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

1505 1506 1507 1508 1509 1510
; Have we got an 8K device?

        MOV     r1, #E2ROMAddress8K
	MOV	r0, #E2ROMAddress8K
	BL	DummyAccess
	MOVVC	R4, #32
1511
        MOVVC   R6, #24         ; Only bottom 6K writable
1512 1513
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
Robert Catherall's avatar
Robert Catherall committed
1514 1515 1516
        BVC     %FT5

; Have we got a 32K device?
1517

Robert Catherall's avatar
Robert Catherall committed
1518 1519 1520 1521 1522 1523 1524
        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
1525
    	BVC 	%FT5
Robert Catherall's avatar
Robert Catherall committed
1526 1527

        MOVVS   R1, #RTCAddress
Dan Ellis's avatar
Dan Ellis committed
1528 1529 1530 1531 1532 1533
        MOVVS   R0, #RTCAddress
    	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
1534 1535 1536 1537 1538 1539 1540
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]
Dan Ellis's avatar
Dan Ellis committed
1541
    	MOV 	R0, #0	    	; Exit failure
1542
        STRB    R0, [R2, #RTCFitted]
Dan Ellis's avatar
Dan Ellis committed
1543
    	EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1544 1545

5
Neil Turton's avatar
Neil Turton committed
1546
	; Set the NVRam count
Kevin Bracey's avatar
Kevin Bracey committed
1547 1548 1549
	STRB    R1, [R2, #NVRamBase]
	STRB	R4, [R2, #NVRamSize]
        STRB    R5, [R2, #NVRamPageSize]
1550 1551 1552
        TEQ     R6, #0
        MOVEQ   R6, R4
        STRB    R6, [R2, #NVRamWriteSize]
Robert Catherall's avatar
Robert Catherall committed
1553 1554 1555

        CMP     R3, #I2Cticks   ; clamp speed to maximum bus speed
        MOVLO   R3, #I2Cticks
Kevin Bracey's avatar
Kevin Bracey committed
1556
        STRB    R3, [R2, #NVRamSpeed]
Dan Ellis's avatar
Dan Ellis committed
1557 1558
06
	; Initialise the cache
Kevin Bracey's avatar
Kevin Bracey committed
1559
	LDR	R3, =CMOSRAMCache
Neil Turton's avatar
Neil Turton committed
1560

Kevin Bracey's avatar
Kevin Bracey committed
1561 1562 1563 1564 1565 1566 1567 1568 1569
        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
1570 1571 1572
    |
	MOV	R1, #RTCAddress
	MOV	R2, #&10
Kevin Bracey's avatar
Kevin Bracey committed
1573 1574
	MOV	R4, #&100		; stop at address &100
	LDR	R3, =CMOSRAMCache
Neil Turton's avatar
Neil Turton committed
1575
    ]
1576 1577 1578

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


1582 1583 1584 1585 1586
        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
1587
        TST     R1, #&100               ; 2-byte address?
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
        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
1607 1608 1609

   [ E2ROMSupport
ReadOTPArea Entry
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
        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
1628
   ]
Neil Turton's avatar
Neil Turton committed
1629

Neil Turton's avatar
Neil Turton committed
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
; *****************************************************************************
;
;	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

; Have we got an RTC ? do a read from location 0 to find out

  [ E2ROMSupport
1644 1645 1646 1647 1648
DummyAccess	Entry "R1,R2"

        MOV     R1, #0
        MOV     R2, #0
        BL      IIC_Op
Neil Turton's avatar
Neil Turton committed
1649 1650 1651 1652

	EXIT				; Exit with V set appropriately
  ]

Kevin Bracey's avatar
Kevin Bracey committed
1653 1654 1655 1656 1657 1658 1659
; *****************************************************************************
;
;       SWI OS_NVMemory
;
; in:   R0 = reason code
;

1660
NVMemorySWI     Entry
Kevin Bracey's avatar
Kevin Bracey committed
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
        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
1683
        RETURNVS
Kevin Bracey's avatar
Kevin Bracey committed
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698

; -----------------------------------------------------------------------------
; 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
1699
        MOV     PC, LR
Kevin Bracey's avatar
Kevin Bracey committed
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709

; -----------------------------------------------------------------------------
; OS_NVMemory 1 - read a byte
;
; in:   R0 = 1
;       R1 = location
;
; out:  R2 = value
;
NVMemory_Read
1710 1711
        Entry   "R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1712
        BIC     R0, R4, #I32_bit
1713
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1714 1715 1716 1717 1718
        MOV     R0, R1
        BL      ReadWithError
        MOVVC   R2, R0
        MOVVC   R0, #1          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1719
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733
        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
        ]
1734 1735
        Entry   "R1,R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1736
        BIC     R0, R4, #I32_bit
1737
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1738 1739 1740 1741 1742
        MOV     R0, R1
        MOV     R1, R2
        BL      WriteWithError
        MOVVC   R0, #2          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1743
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 3 - read a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_ReadBlock
1755
        Entry   "R1-R4"
Kevin Bracey's avatar
Kevin Bracey committed
1756
        MOV     R4, PC
1757
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1758
        BIC     R0, R4, #I32_bit
1759
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1760 1761 1762 1763 1764 1765
        MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      ReadBlock
        MOVVC   R0, #3          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1766
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 4 - write a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_WriteBlock ROUT
1778 1779
        Entry   "R1-R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1780
        BIC     R0, R4, #I32_bit
1781
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795
        [ 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
1796
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1797 1798
        EXIT

Neil Turton's avatar
Neil Turton committed
1799
	END