sdcmos 13.9 KB
Newer Older
Ben Avison's avatar
Ben Avison committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
;
; 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
; cddl/RiscOS/Sources/FileSys/SDFS/SDFS/LICENCE.
; 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
 [ :LNOT::DEF: StoreInHAL
        GBLL    StoreInHAL
StoreInHAL SETL {FALSE};
 ]

31 32 33 34 35 36 37 38 39 40 41 42 43 44
        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
45
        GET     Hdr:MsgTrans
46
        GET     Hdr:RTC
47 48
        GET     Hdr:HALDevice
        GET     Hdr:HALEntries
Ben Avison's avatar
Ben Avison committed
49 50 51 52 53 54 55 56 57
        GET     VersionASM

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

        ENTRY

        DCD     0 ; Start
        DCD     Init - |Asm$$Code|
        DCD     Final - |Asm$$Code|
58 59 60 61 62
      [ StoreInHAL
        DCD     Services - |Asm$$Code|
      |
        DCD     0 ; Service call handler
      ]
Ben Avison's avatar
Ben Avison committed
63 64 65 66 67 68 69 70 71 72 73 74 75
        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
76
Flags   DCD     ModuleFlag_32bit
Ben Avison's avatar
Ben Avison committed
77

78 79 80 81
 [ StoreInHAL

NonCanonicalisedPath
        =       "SDFS::0.$.!Boot.Loader.riscos/img", 0
82 83
NonCanonicalisedPath2
        =       "SDFS::0.$.riscos/img", 0
84 85 86 87 88 89 90
        ALIGN

CMOSMarker UND  #&C305
OSIm    =       "OSIm"

 |

Ben Avison's avatar
Ben Avison committed
91 92
NonCanonicalisedPath
        =       "SDFS::0.$.CMOS", 0
93 94
NonCanonicalisedPath2
        =       "SDFS::0.$.!Boot.Loader.CMOS", 0
Ben Avison's avatar
Ben Avison committed
95 96
        ALIGN

97 98
ReqdAPIMajor *  0

Ben Avison's avatar
Ben Avison committed
99 100 101 102 103
SaveCMOS
        =       "SaveCMOS "
Len_SaveCMOS * .-SaveCMOS
        ALIGN

104 105
 ]

Ben Avison's avatar
Ben Avison committed
106 107
Init    ROUT
        Entry
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
      [ :LNOT: StoreInHAL
        ; 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
128 129 130 131
        ADR     r0, ErrorBlock_HardwareDepends
        MOV     r1, #0
        MOV     r2, #0
        SWI     XMessageTrans_ErrorLookup
132 133
        EXIT
20
Robert Sprowson's avatar
Robert Sprowson committed
134
        MakeInternatErrorBlock HardwareDepends,,HWDep
135 136 137
30
        MOV     r8, r6
      ]
Ben Avison's avatar
Ben Avison committed
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
        ; 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

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

157 158 159 160
        ADR     r1, NonCanonicalisedPath
        BL      TryInit
        ADRVS   r1, NonCanonicalisedPath2
        BLVS    TryInit
161
        BVS     %FT90
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

        ; All good - get on ByteV
        MOV     r0, #ByteV
        ADR     r1, MyByteV
        MOV     r2, r12
        SWI     XOS_Claim
        BVS     %F90
        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


; In: r1 = filename
; Out: Regs corrupt
;      V set on failure
;      No error pointer returned
TryInit ROUT
        Entry
Ben Avison's avatar
Ben Avison committed
198 199 200 201 202 203 204 205 206
        ; 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

207 208 209 210
      [ StoreInHAL
        ; Allocate a buffer to hold filename of the ROM image plus terminator
        RSB     r3, r5, #1
      |
Ben Avison's avatar
Ben Avison committed
211 212 213
        ; 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
214 215
      ]
        MOV     r0, #ModHandReason_Claim
Ben Avison's avatar
Ben Avison committed
216 217 218 219 220
        SWI     XOS_Module
        BVS     %F90
        STR     r2, [r12]

        ; Get the canonicalised name
221
      [ :LNOT: StoreInHAL
Ben Avison's avatar
Ben Avison committed
222
        ADD     r2, r2, #Len_SaveCMOS
223
      ]
Ben Avison's avatar
Ben Avison committed
224 225 226 227 228 229
        MOV     r5, r3
        MOV     r0, #FSControl_CanonicalisePath
        MOV     r3, #0
        SWI     XOS_FSControl
        BVS     %F90

230
      [ :LNOT: StoreInHAL
Ben Avison's avatar
Ben Avison committed
231 232 233 234 235 236 237 238
        ; 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
239
      ]
Ben Avison's avatar
Ben Avison committed
240

241
        ; Check it's a file (or image file)
Ben Avison's avatar
Ben Avison committed
242 243 244 245 246 247
        MOV     r0, #OSFile_ReadWithTypeNoPath
        MOV     r1, r2
        SWI     XOS_File
        BVS     %F90
        TST     r0, #object_file
        BEQ     %F90
248 249 250

      [ :LNOT: StoreInHAL
        ; Check it's a sensible filetype
Ben Avison's avatar
Ben Avison committed
251 252
        LDR     r0, =FileType_Configuration
        TEQ     r6, r0
253 254
        LDRNE   r0, =FileType_MSDOS
        TEQNE   r6, r0
Ben Avison's avatar
Ben Avison committed
255
        BNE     %F90
256 257 258 259 260
      |
        ; 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
261
        MOV     r1, #OWReadRTC_5ByteInt
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
        STRB    r1, [sp]
        MOV     r1, sp
        SWI     XOS_Word
        ADDVS   sp, sp, #8
        BVS     %F80

        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
        ADDPL   sp, sp, #8  ; now > 1970
        BPL     %F80

        ; Try and find the last saved value
        MOV     r0, #open_read :OR: open_mustopen :OR: open_nodir :OR: open_nopath
        LDR     r1, [r12]
        SWI     XOS_Find
        BVS     %F70
        MOV     r1, r0

        ; Search for the CMOS in the ROM on disc
        LDR     r5, CMOSMarker
        LDR     r6, OSIm
        MOV     r0, #OSGBPB_ReadFromPTR
50      MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F60
        LDR     r14, [sp]
        TEQ     r14, r6
        BEQ     %F60        ; got to the end of the HAL and not found CMOS - give up
        TEQ     r14, r5
        BNE     %B50

299
        ; Read size of pseudo CMOS in HAL
300 301 302 303 304 305
        MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F60
        LDR     r6, [sp]

306 307 308 309
        ; If there's no RTC, try restoring the time from the HAL timestamp
        SWI     XRTC_Features
        BVC     %F60        ; V clear -> RTC driver is active

310 311 312 313 314 315 316 317 318 319 320 321 322
        ; Read the last timestamp
        MOV     r0, #OSGBPB_ReadFromGiven
        MOV     r2, sp
        MOV     r3, #5
        ADD     r4, r4, r6
        SWI     XOS_GBPB
        BVS     %F60

        ; Check it's not unset
        LDR     r3, [sp, #0]
        LDRB    r4, [sp, #4]
        ORRS    r3, r4, r3
        MOVNE   r0, sp
323 324
        SWINE   XTerritory_SetTime
        CLRV
325 326 327 328 329 330 331 332 333
60
        MRS     r3, CPSR    ; preserve V set ness
        MOV     r0, #0      ; close file
        SWI     XOS_Find
        MSR     CPSR_f, r3
70
        ADD     sp, sp, #8  ; skip temp block
        BVS     %F90
80
334
      ]
335 336 337
        ; All good
        CLRV
        EXIT
Ben Avison's avatar
Ben Avison committed
338

339 340 341 342 343 344 345 346 347 348 349
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
350

351 352 353 354 355 356 357 358 359 360 361 362
      [ StoreInHAL
Services ROUT
        TEQ     r1, #Service_ShutDown
        MOVNE   pc, lr
        Push    "r0, lr"    ; keep original r0 in case MyByteV returns an error
        Push    "pc"
        BL      %FT15       ; now write the values out, along with the timestamp
        NOP
        Pull    "r0, pc"    ; and on with the shutdown (don't claim)
      ]

MyByteV
Ben Avison's avatar
Ben Avison committed
363 364
        TEQ     r0, #OsByte_WriteCMOS
        MOVNE   pc, lr      ; only interested in when the CMOS is written
365
        ADR     r0, %F10
Ben Avison's avatar
Ben Avison committed
366 367 368
        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...
369
10                          ; ... we end up here after the CMOS has been written
Ben Avison's avatar
Ben Avison committed
370 371
        Pull    "r12"       ; get our own r12 back
        Pull    "pc", VS    ; if an error, just pass it up to original claim address
372
      [ StoreInHAL
373
15
374
        Push    "r0-r7"
375 376 377
        SUB     sp, sp, #4  ; allocate space on stack for buffer

        MOV     r7, r1
378
        MOV     r0, #open_update :OR: open_mustopen :OR: open_nodir :OR: open_nopath
379 380 381 382 383 384 385 386 387
        LDR     r1, [r12]
        SWI     XOS_Find
        BVS     %F90
        MOV     r1, r0

        ; Search for the CMOS in the ROM on disc - can't be sure it matches the
        ; running version!
        LDR     r5, CMOSMarker
        LDR     r6, OSIm
388
        MOV     r0, #OSGBPB_ReadFromPTR
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 422 423 424 425 426
20      MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F80
        LDR     r14, [sp]
        TEQ     r14, r6
        BEQ     %F80        ; got to the end of the HAL and not found CMOS - give up
        TEQ     r14, r5
        BNE     %B20

        ; Read size of block in HAL
        MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F80
        LDR     r6, [sp]
        MOV     r5, r1      ; keep file handle safe

        ; 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

        ; Overwrite the HAL with the block from the stack
427
        MOV     r0, #OSGBPB_WriteAtPTR
428 429 430 431
        MOV     r1, r5
        MOV     r2, sp
        MOV     r3, r6
        SWI     XOS_GBPB
432 433 434 435
        BVS     %F75

        ; Refresh the timestamp
        MOV     r0, #OsWord_ReadRealTimeClock
436
        MOV     r1, #OWReadRTC_5ByteInt
437 438 439 440 441 442 443 444 445 446
        STRB    r1, [sp]
        MOV     r1, sp
        SWI     XOS_Word

        MOVVC   r0, #OSGBPB_WriteAtPTR
        MOVVC   r1, r5
        MOVVC   r2, sp
        MOVVC   r3, #5
        SWIVC   XOS_GBPB
75
447 448
        ADD     sp, sp, r6

449
80      MOV     r2, r0      ; preserve the original error
450 451 452 453 454
        MRS     r3, CPSR
        MOV     r0, #0      ; close file
        SWI     XOS_Find
        MOV     r0, r2
        MSR     CPSR_f, r3
455
90      ADD     sp, sp, #4  ; skip temp block
456
        STRVS   r0, [sp]
457
        Pull    "r0-r7, pc" ; go to original claim address
458
      |
Ben Avison's avatar
Ben Avison committed
459 460 461 462 463
        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
464
      ]
Ben Avison's avatar
Ben Avison committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479

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

480
        ; The block pointed at by r12 is freed for us by the kernel if nonzero
Ben Avison's avatar
Ben Avison committed
481 482 483 484 485

        CLRV
        EXIT

        END