sdcmos 11.8 KB
Newer Older
Ben Avison's avatar
Ben Avison committed
1 2 3 4 5 6 7 8
;
; CDDL HEADER START
;
; The contents of this file are subject to the terms of the
; Common Development and Distribution License (the "Licence").
; You may not use this file except in compliance with the Licence.
;
; You can obtain a copy of the licence at
Robert Sprowson's avatar
Robert Sprowson committed
9
; cddl/RiscOS/Sources/HWSupport/SD/SDCMOS/LICENCE.
Ben Avison's avatar
Ben Avison committed
10 11 12 13 14 15 16 17 18 19 20 21
; See the Licence for the specific language governing permissions
; and limitations under the Licence.
;
; When distributing Covered Code, include this CDDL HEADER in each
; file and include the Licence file. If applicable, add the
; following below this CDDL HEADER, with the fields enclosed by
; brackets "[]" replaced with your own identifying information:
; Portions Copyright [yyyy] [name of copyright owner]
;
; CDDL HEADER END
;
; Copyright 2012 Ben Avison.  All rights reserved.
22
; Portions Copyright 2012 Jeffrey Lee.
Ben Avison's avatar
Ben Avison committed
23 24 25
; Use is subject to license terms.
;

26 27 28 29 30 31 32 33 34 35 36 37 38 39
        GET     Hdr:ListOpts
        GET     Hdr:Macros
        GET     Hdr:System
        GET     Hdr:Proc
        GET     Hdr:HighFSI
        GET     Hdr:ModHand
        GET     Hdr:OsBytes
        GET     Hdr:OsWords
        GET     Hdr:CMOS
        GET     Hdr:FSNumbers
        GET     Hdr:NewErrors
        GET     Hdr:Territory
        GET     Hdr:FileTypes
        GET     Hdr:Services
Robert Sprowson's avatar
Robert Sprowson committed
40
        GET     Hdr:MsgTrans
41
        GET     Hdr:RTC
42 43
        GET     Hdr:HALDevice
        GET     Hdr:HALEntries
Ben Avison's avatar
Ben Avison committed
44
        GET     Hdr:SDFS
Ben Avison's avatar
Ben Avison committed
45 46 47 48 49 50 51 52 53
        GET     VersionASM

        AREA    |Asm$$Code|, CODE, READONLY, PIC

        ENTRY

        DCD     0 ; Start
        DCD     Init - |Asm$$Code|
        DCD     Final - |Asm$$Code|
Robert Sprowson's avatar
Robert Sprowson committed
54
      [ :LNOT::DEF: StoreAtDiscAddress
55 56 57 58
        DCD     Services - |Asm$$Code|
      |
        DCD     0 ; Service call handler
      ]
Ben Avison's avatar
Ben Avison committed
59 60 61 62 63 64 65 66 67 68 69 70 71
        DCD     Title - |Asm$$Code|
        DCD     Help - |Asm$$Code|
        DCD     0 ; Keyword table
        DCD     0 ; SWI chunk
        DCD     0 ; SWI handler
        DCD     0 ; SWI table
        DCD     0 ; SWI decoder
        DCD     0 ; Messages
        DCD     Flags - |Asm$$Code|

Title   =       Module_ComponentName, 0
Help    =       Module_ComponentName, 9, 9, Module_HelpVersion, 0
        ALIGN
72
Flags   DCD     ModuleFlag_32bit
Ben Avison's avatar
Ben Avison committed
73

Robert Sprowson's avatar
Robert Sprowson committed
74
      [ :LNOT::DEF: StoreAtDiscAddress
75

Ben Avison's avatar
Ben Avison committed
76
NonCanonicalisedPath
77
        =       "SDFS:$.CMOS", 0
78
NonCanonicalisedPath2
79
        =       "SDFS:$.!Boot.Loader.CMOS", 0
Ben Avison's avatar
Ben Avison committed
80 81 82 83 84 85 86
        ALIGN

SaveCMOS
        =       "SaveCMOS "
Len_SaveCMOS * .-SaveCMOS
        ALIGN

Robert Sprowson's avatar
Robert Sprowson committed
87
      ]
88

Ben Avison's avatar
Ben Avison committed
89 90
ReqdAPIMajor *  0

Ben Avison's avatar
Ben Avison committed
91 92
Init    ROUT
        Entry
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
        ; If the HAL proclaims hardware CMOS is present, go dormant
        MOV     r6, r8
        MOV     r1, #0
10
        LDR     r0, =(HALDeviceType_SysPeri + HALDeviceSysPeri_NVRAM) :OR: (ReqdAPIMajor:SHL:16)
        MOV     r8, #OSHW_DeviceEnumerate
        SWI     XOS_Hardware
        EXIT    VS

        CMP     r1, #-1                 ; All done with no matches, try file
        BEQ     %FT30

        LDRH    r3, [r2, #HALDevice_ID]
        TEQ     r3, #HALDeviceID_NVRAM_24C02
        TEQNE   r3, #HALDeviceID_NVRAM_24C04
        TEQNE   r3, #HALDeviceID_NVRAM_24C08
        TEQNE   r3, #HALDeviceID_NVRAM_24C16
        BNE     %BT10                   ; Was NVRAM, but not a known one

Robert Sprowson's avatar
Robert Sprowson committed
112 113 114 115
        ADR     r0, ErrorBlock_HardwareDepends
        MOV     r1, #0
        MOV     r2, #0
        SWI     XMessageTrans_ErrorLookup
116 117
        EXIT
20
Robert Sprowson's avatar
Robert Sprowson committed
118
        MakeInternatErrorBlock HardwareDepends,,HWDep
119 120
30
        MOV     r8, r6
Robert Sprowson's avatar
Robert Sprowson committed
121

Ben Avison's avatar
Ben Avison committed
122 123 124 125 126 127 128 129 130 131 132 133 134
        ; This module is designed to be included in a ROM, in which case we have
        ; to take account of the fact that SDFS::0 isn't properly initialised
        ; until the callbacks after ROM init.
        ADR     r0, CallBackFromInit
        MOV     r1, r12
        SWI     XOS_AddCallBack
        EXIT

CallBackFromInit ROUT
        Push    "lr" ; separate instructions to reduce warnings
        ADD     lr, sp, #4
        Push    "r0-r6, lr" ; yes, need to stack sp

Ben Avison's avatar
Ben Avison committed
135
      [ :LNOT::DEF: StoreAtDiscAddress
Ben Avison's avatar
Ben Avison committed
136 137 138 139 140 141
        ; We assume that we're entered during or soon after boot. In which case,
        ; if there is an SD card inserted, and if it contains a file called
        ; "CMOS" in its root directory of the correct filetype, then we must
        ; assume that it could have been used to initialise the kernel's CMOS
        ; RAM cache, and therefore needs updating whenever someone writes CMOS.

142 143 144 145
        ADR     r1, NonCanonicalisedPath
        BL      TryInit
        ADRVS   r1, NonCanonicalisedPath2
        BLVS    TryInit
146
        BVS     %FT90
Ben Avison's avatar
Ben Avison committed
147
      ]
148 149 150 151 152 153 154

        ; All good - get on ByteV
        MOV     r0, #ByteV
        ADR     r1, MyByteV
        MOV     r2, r12
        SWI     XOS_Claim
        BVS     %F90
155 156 157 158 159 160 161 162 163 164 165 166

        ; See if a CMOS reset has occurred, if so our copy on the SD card
        ; is stale and we need to write out the Kernel's clean reset copy
        MOV     r0, #OsByte_ReadCMOS
        MOV     r1, #SystemSpeedCMOS
        SWI     XOS_Byte
        MOVVS   r2, #0
        TST     r2, #CMOSResetBit
        MOVNE   r0, #OsByte_WriteCMOS
        SWINE   XOS_Byte ; just echo it back to trigger a SaveCMOS
        CLRV

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
        Pull    "r0-r6, lr" ; separate instructions to reduce warnings
        Pull    "pc"

90      ; Error detected during callback - kill the module and exit
        ASSERT  %F99-%F98 = 8
        ADR     r0, %F98
        LDMIA   r0, {r1-r2}
        Push    "r1-r2"
        MOV     r0, #1
        MOV     r1, sp
        ADD     r2, sp, #%F99-%F98-1
        SWI     XOS_SynchroniseCodeAreas
        MOV     r0, #ModHandReason_Delete
        ADR     r1, Title
        ADD     r2, sp, #%F99-%F98 ; point r2 at stack frame
        MOV     pc, sp
        ; This last bit is executed after the module is killed so can't safely
        ; be executed in place - do it from the stack instead
98      SWI     XOS_Module
        LDMIA   r2, {r0-r6, sp, pc} ; atomic update of sp (which makes this code volatile) with pc
99


Robert Sprowson's avatar
Robert Sprowson committed
190
      [ :LNOT::DEF: StoreAtDiscAddress
191 192 193 194 195 196
; In: r1 = filename
; Out: Regs corrupt
;      V set on failure
;      No error pointer returned
TryInit ROUT
        Entry
Ben Avison's avatar
Ben Avison committed
197 198 199 200 201 202 203 204 205 206 207 208
        ; Find how long the canonicalised name is
        MOV     r0, #FSControl_CanonicalisePath
        MOV     r2, #0
        MOV     r3, #0
        MOV     r4, #0
        MOV     r5, #0
        SWI     XOS_FSControl
        BVS     %F90

        ; Allocate a buffer for the command string - will contain "SaveCMOS "
        ; plus the canonicalised name of the file, plus a terminator
        RSB     r3, r5, #Len_SaveCMOS + 1
209
        MOV     r0, #ModHandReason_Claim
Ben Avison's avatar
Ben Avison committed
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
        SWI     XOS_Module
        BVS     %F90
        STR     r2, [r12]

        ; Get the canonicalised name
        ADD     r2, r2, #Len_SaveCMOS
        MOV     r5, r3
        MOV     r0, #FSControl_CanonicalisePath
        MOV     r3, #0
        SWI     XOS_FSControl
        BVS     %F90

        ; Copy in the "SaveCMOS " part now we have a few more working registers
        ASSERT  Len_SaveCMOS = 9
        SUB     r2, r2, #Len_SaveCMOS
        ADR     r3, SaveCMOS
        LDMIA   r3!, {r4-r5}
        LDRB    r6, [r3]
        STMIA   r2!, {r4-r5}
        STRB    r6, [r2], #1

231
        ; Check it's a file (or image file)
Ben Avison's avatar
Ben Avison committed
232 233 234 235 236 237
        MOV     r0, #OSFile_ReadWithTypeNoPath
        MOV     r1, r2
        SWI     XOS_File
        BVS     %F90
        TST     r0, #object_file
        BEQ     %F90
238 239

        ; Check it's a sensible filetype
Ben Avison's avatar
Ben Avison committed
240 241
        LDR     r0, =FileType_Configuration
        TEQ     r6, r0
242 243
        LDRNE   r0, =FileType_MSDOS
        TEQNE   r6, r0
Ben Avison's avatar
Ben Avison committed
244
        BNE     %F90
Robert Sprowson's avatar
Robert Sprowson committed
245 246 247 248 249 250 251 252 253 254 255

        ; If there's no RTC, try restoring the time from the file timestamp
        SWI     XRTC_Features
        BVC     %F80        ; V clear -> RTC driver is active

        AND     r4, r2, #&FF
        ORRS    r0, r4, r3
        BEQ     %F80        ; Clearly duff load/exec address (timestamp)

        Push    "r3-r4"

256 257 258 259
        ; If the time is in 1970 then the kernel didn't find a real time
        ; clock, and NetTime hasn't picked up a link yet
        SUB     sp, sp, #8
        MOV     r0, #OsWord_ReadRealTimeClock
260
        MOV     r1, #OWReadRTC_5ByteInt
261 262 263 264
        STRB    r1, [sp]
        MOV     r1, sp
        SWI     XOS_Word
        ADDVS   sp, sp, #8
Robert Sprowson's avatar
Robert Sprowson committed
265
        BVS     %F60
266 267 268 269 270 271 272 273

        LDR     r3, =((71 * 365) + 18) * 86400
        MOV     r0, #100    ; want cs to end of 1970 from epoch 1900
        UMULL   r3, r4, r0, r3
        LDR     r0, [sp, #0]
        LDRB    r1, [sp, #4]
        SUBS    r14, r0, r3
        SBCS    r14, r1, r4
Robert Sprowson's avatar
Robert Sprowson committed
274 275
        ADD     sp, sp, #8
        BPL     %F60        ; now > 1970
276

Robert Sprowson's avatar
Robert Sprowson committed
277 278 279
        ; Use load/exec address (timestamp) as a better guess
        MOV     r0, sp
        SWI     XTerritory_SetTime
280
        CLRV
281
60
Robert Sprowson's avatar
Robert Sprowson committed
282
        ADD     sp, sp, #8  ; Drop load/exec address
283
80
284 285 286
        ; All good
        CLRV
        EXIT
Ben Avison's avatar
Ben Avison committed
287

288 289 290 291 292 293 294 295 296 297 298
90
        ; Something went wrong
        ; Free our workspace to avoid potential leak if TryInit called multiple times
        LDR     r2, [r12]
        CMP     r2, #0
        MOVNE   r0, #ModHandReason_Free
        SWINE   XOS_Module
        MOV     r2, #0
        STR     r2, [r12]
        SETV
        EXIT
Ben Avison's avatar
Ben Avison committed
299

300 301 302
Services ROUT
        TEQ     r1, #Service_ShutDown
        MOVNE   pc, lr
Robert Sprowson's avatar
Robert Sprowson committed
303 304 305 306 307 308
        Push    "r0-r1, lr" ; keep original r0 in case OS_File returns an error
        LDR     r1, [r12]
        ADD     r1, r1, #Len_SaveCMOS
        MOV     r0, #OSFile_SetStamp
        SWI     XOS_File    ; stamp at shutdown so file timestamp is fresh
        Pull    "r0-r1, pc" ; and on with the shutdown (don't claim)
309 310 311
      ]

MyByteV
Ben Avison's avatar
Ben Avison committed
312 313
        TEQ     r0, #OsByte_WriteCMOS
        MOVNE   pc, lr      ; only interested in when the CMOS is written
314
        ADR     r0, %F10
Ben Avison's avatar
Ben Avison committed
315 316 317
        Push    "r0, r12"   ; set up address for claimant to return to (NB this code is not 26-bit compatible)
        MOV     r0, #OsByte_WriteCMOS
        MOV     pc, lr      ; pass on, and...
318
10                          ; ... we end up here after the CMOS has been written
Ben Avison's avatar
Ben Avison committed
319 320
        Pull    "r12"       ; get our own r12 back
        Pull    "pc", VS    ; if an error, just pass it up to original claim address
Ben Avison's avatar
Ben Avison committed
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
      [ :DEF: StoreAtDiscAddress
        Push    "r0-r4,r6"
        MOV     r6, #0
        MOV     r0, #1
        MOV     r1, #StoreAtDiscAddress :SHR: 29
        MOV     r2, #0
        SWI     XSDFS_MiscOp
        BVS     %F75
        TEQ     r2, #1
        BNE     %F75 ; disc has been changed since boot - don't write to it

        MOV     r6, #256
        BL      CMOSToStack

        MOV     r1, #2
        LDR     r2, =StoreAtDiscAddress
        MOV     r3, sp
        MOV     r4, r6
        SWI     XSDFS_DiscOp
75
        ADD     sp, sp, r6
        STRVS   r0, [sp]
        Pull    "r0-r4,r6, pc" ; go to original claim address
344
      |
Ben Avison's avatar
Ben Avison committed
345 346 347 348 349
        Push    "r0"
        LDR     r0, [r12]
        SWI     XOS_CLI     ; save the CMOS to the file
        STRVS   r0, [sp]
        Pull    "r0, pc"    ; go to original claim address
350
      ]
Ben Avison's avatar
Ben Avison committed
351

Robert Sprowson's avatar
Robert Sprowson committed
352
      [ :DEF: StoreAtDiscAddress
Ben Avison's avatar
Ben Avison committed
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
CMOSToStack ROUT
        MOV     r4, lr
        ; Copy the CMOS RAM into a block on the stack (should be small enough)
        ; in physical address order
        SUB     sp, sp, r6
        MOV     r3, #0
30      MOV     r0, #OsByte_ReadCMOS
        MOV     r1, r3
        CMP     r3, #&10
        ADDLO   r1, r1, #&40
        CMP     r3, #&40
        ADDLO   r1, r1, #&F0
        CMP     r3, #&100
        SUBLO   r1, r1, #&40
        SWI     XOS_Byte
        MOVVS   r2, #0
        STRB    r2, [sp, r3]
        ADD     r3, r3, #1
        CMP     r3, r6
        BLO     %B30
        MOV     pc, r4
      ]

Ben Avison's avatar
Ben Avison committed
376 377 378 379 380 381 382 383 384 385 386 387 388 389
Final   ROUT
        Entry
        ; It's good practice to remove our callback here just in case we got
        ; killed before it was triggered.
        ADR     r0, CallBackFromInit
        MOV     r1, r12
        SWI     XOS_RemoveCallBack

        ; Get off ByteV, if we were on it
        MOV     r0, #ByteV
        ADR     r1, MyByteV
        MOV     r2, r12
        SWI     XOS_Release

390
        ; The block pointed at by r12 is freed for us by the kernel if nonzero
Ben Avison's avatar
Ben Avison committed
391 392 393 394 395

        CLRV
        EXIT

        END