MemInfo 55.6 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 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
; 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.
;
; > MemInfo

        LTORG

;----------------------------------------------------------------------------------------
; MemorySWI
;
;       In:     r0 = reason code and flags
;                       bits 0-7  = reason code
;                       bits 3-31 = reason specific flags
;       Out:    specific to reason codes
;
;       Perform miscellaneous operations for memory management.
;
MemorySWI       ROUT
        Push    lr                              ; Save real return address.
        AND     lr, r0, #&FF                    ; Get reason code.
        CMP     lr, #(%40-%30):SHR:2            ; If valid reason code then
        ADDCC   lr, lr, #(%30-%10):SHR:2        ;   determine where to jump to in branch table,
        ADDCC   lr, pc, lr, LSL #2
        Push    lr, CC                          ;   save address so we can
10
        ADRCC   lr, MemReturn                   ;   set up default return address for handler routines
        Pull    pc, CC                          ;   and jump into branch table.
20
        ADRL    r0, ErrorBlock_HeapBadReason    ; Otherwise, unknown reason code.
        SETV
        ; Drop through to...

MemReturn
 [ International
        BLVS    TranslateError
 ]
        Pull    lr                              ; Get back real return address.
        BVS     SLVK_SetV
        ExitSWIHandler

30
53
        B       MemoryConvert                   ; 0
Neil Turton's avatar
Neil Turton committed
54 55 56 57 58
        B       %BT20                           ; Reason codes 1-5 are reserved.
        B       %BT20
        B       %BT20
        B       %BT20
        B       %BT20
59 60 61 62
        B       MemoryPhysSize                  ; 6
        B       MemoryReadPhys                  ; 7
        B       MemoryAmounts                   ; 8
        B       MemoryIOSpace                   ; 9
63
        B       MemoryFreePoolLock              ; 10
64
        B       %BT20                           ; Reason code 11 reserved (for PCImapping).
65 66 67 68
        B       RecommendPage                   ; 12
        B       MapIOpermanent                  ; 13
        B       AccessPhysAddr                  ; 14
        B       ReleasePhysAddr                 ; 15
69
        B       MemoryAreaInfo                  ; 16
70 71 72 73 74 75 76 77 78
        B       %BT20                           ; 17 |
        B       %BT20                           ; 18 |
        B       %BT20                           ; 19 |
        B       %BT20                           ; 20 | Reserved for us
        B       %BT20                           ; 21 |
        B       %BT20                           ; 22 |
        B       %BT20                           ; 23 |
        B       CheckMemoryAccess               ; 24
                                                ; 25+ reserved for ROL
Neil Turton's avatar
Neil Turton committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
40


;----------------------------------------------------------------------------------------
; MemoryConvert
;
;       In:     r0 = flags
;                       bit     meaning
;                       0-7     0 (reason code)
;                       8       page number provided when set
;                       9       logical address provided when set
;                       10      physical address provided when set
;                       11      fill in page number when set
;                       12      fill in logical address when set
;                       13      fill in physical address when set
;                       14-15   0,1=don't change cacheability
;                               2=disable caching on these pages
;                               3=enable caching on these pages
;                       16-31   reserved (set to 0)
;               r1 -> page block
;               r2 = number of 3 word entries in page block
;
;       Out:    r1 -> updated page block
;
;       Converts between representations of memory addresses. Can also set the
;       cacheability of the specified pages.
;

; Declare symbols used for decoding flags (given and wanted are used
; so that C can be cleared by rotates of the form a,b). We have to munge
; the flags a bit to make the rotates even.
;
ppn             *       1:SHL:0         ; Bits for address formats.
logical         *       1:SHL:1
physical        *       1:SHL:2
all             *       ppn :OR: logical :OR: physical
given           *       24              ; Rotate for given fields.
wanted          *       20              ; Rotate for wanted fields.
ppn_bits        *       ((ppn :SHL: 4) :OR: ppn)
logical_bits    *       ((logical :SHL: 4) :OR: logical)
physical_bits   *       ((physical :SHL: 4) :OR: physical)
cacheable_bit   *       1:SHL:15
alter_cacheable *       1:SHL:16

MemoryConvert   ROUT
124
        Entry   "r0-r11"                ; Need lots of registers!!
Neil Turton's avatar
Neil Turton committed
125

Kevin Bracey's avatar
Kevin Bracey committed
126 127 128 129 130
;        MRS     lr, CPSR
;        Push    "lr"
;        ORR     lr, lr, #I32_bit+F32_bit
;        MSR     CPSR_c, lr

Neil Turton's avatar
Neil Turton committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144
        BIC     lr, r0, #all,given      ; Need to munge r0 to get rotates to work (must be even).
        AND     r0, r0, #all,given
        ORR     r0, r0, lr, LSL #1      ; Move bits 11-30 to 12-31.

        TST     r0, #all,given          ; Check for invalid argument (no fields provided)
        TEQNE   r2, #0                  ;   (no entries in table).
        ADREQL  r0, ErrorBlock_BadParameters
        BEQ     %FT95

        EOR     lr, r0, r0, LSL #given-wanted   ; If flag bits 8-10 and 12-14 contain common bits then
        AND     lr, lr, #all,wanted             ;   clear bits in 12-14 (ie. don't fill in fields already given).
        EOR     lr, lr, #all,wanted
        BIC     r0, r0, lr

Jeffrey Lee's avatar
Jeffrey Lee committed
145
        LDR     r6, =ZeroPage
Neil Turton's avatar
Neil Turton committed
146 147 148 149 150 151 152 153 154
        LDR     r7, [r6, #MaxCamEntry]
        LDR     r6, [r6, #CamEntriesPointer]
        LDR     r8, =L2PT
10
        SUBS    r2, r2, #1
        BCC     %FT70

        LDMIA   r1!, {r3-r5}            ; Get next three word entry (PN,LA,PA) and move on pointer.

155 156 157 158
   [ ChocolateAMB
        BL      handle_AMBHonesty       ; may need to make page honest (as if not lazily mapped)
   ]

Neil Turton's avatar
Neil Turton committed
159 160 161 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 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
        TST     r0, #physical,wanted    ; If PA not wanted
        BEQ     %FT20                   ;   then skip.
        TST     r0, #logical,given      ; If LA not given (rotate clears C) then
        BLEQ    ppn_to_logical          ;   get it from PN (PA wanted (not given) & LA not given => PN given).
        BLCC    logical_to_physical     ; Get PA from LA.
        BCS     %FT80
        TST     r0, #logical,wanted
        STRNE   r4, [r1, #-8]           ; Store back LA if wanted.
        STR     r5, [r1, #-4]           ; Store back PA.
20
        TST     r0, #alter_cacheable    ; If altering cacheability
        EORNE   lr, r0, #ppn,given      ;   and PN not given
        TSTNE   lr, #ppn,given
        TSTEQ   r0, #ppn,wanted         ;   OR PN wanted then don't skip
        BEQ     %FT30                   ; else skip.
        TST     r0, #physical_bits,given        ; If PA not given and PA not wanted (rotate clears C) then
        BLEQ    logical_to_physical             ;   get it from LA (PN wanted/not given & PA not given => LA given).
        BLCC    physical_to_ppn         ; Get PN from PA.
        BCS     %FT80
        TST     r0, #ppn,wanted
        STRNE   r3, [r1, #-12]          ; Store back PN if wanted.
30
        TST     r0, #logical,wanted     ; If LA wanted
        EORNE   lr, r0, #physical,wanted
        TSTNE   lr, #physical,wanted    ;   and PA not wanted then don't skip
        BEQ     %FT40                   ; else skip.
        TST     r0, #alter_cacheable    ; If not changing cacheability (already have PN)
        TSTEQ   r0, #ppn_bits,given     ;   and PN not given and PN not wanted (rotate clears C) then
        BLEQ    physical_to_ppn         ;   get it from PA (LA wanted (not given) & PN not given => PA given).
        BLCC    ppn_to_logical          ; Get LA from PN.
        BCS     %FT80
        STR     r4, [r1, #-8]           ; Store back LA.
40
        TST     r0, #alter_cacheable
        BEQ     %BT10

        CMP     r7, r3                  ; Make sure page number is valid (might not have done any conversion).
        BCC     %FT80

        ADD     r3, r6, r3, LSL #3      ; Point to CAM entry for this page.
        LDMIA   r3, {r4,r5}             ; Get logical address and PPL.

        AND     lr, r5, #PageFlags_TempUncacheableBits
        TST     r0, #cacheable_bit
        BNE     %FT50

        TEQ     lr, #PageFlags_TempUncacheableBits      ; Make uncacheable (increment count).
        BEQ     %BT10                                   ; If count has reached max then go no further (should not happen).
        TEQ     lr, #0                                  ; EQ => we have to change L2.
        ADD     r5, r5, #1:SHL:TempUncacheableShift
        B       %FT60
50
        TEQ     lr, #0                                  ; Make cacheable (decrement count).
        BEQ     %BT10                                   ; If count is already 0 then go no further (page already cacheable).
        SUB     r5, r5, #1:SHL:TempUncacheableShift
        TST     r5, #PageFlags_TempUncacheableBits      ; EQ => we have to change L2.
60
        STR     r5, [r3, #4]            ; Write back new PPL.
        BNE     %BT10                   ; Do next entry if we don't have to change L2.

        MOV     r4, r4, LSR #12
        ADD     r4, r8, r4, LSL #2      ; Address of L2 entry for logical address.
        LDR     r5, [r4]                ; Get L2 entry (safe as we know address is valid).
        TST     r0, #cacheable_bit
        BICEQ   r5, r5, #L2_C           ; Disable/enable cacheability.
        ORRNE   r5, r5, #L2_C
        STR     r5, [r4]                ; Write back new L2 entry.
226 227 228
        MOV     r5, r0
        ASSERT  (L2PT :SHL: 12) = 0     ; Ensure we can convert r4 back to the page log addr
        MOV     r0, r4, LSL #10
Kevin Bracey's avatar
Kevin Bracey committed
229 230
        ; *** KJB - this assumes that uncacheable pages still allow cache hits (true on all
        ; ARMs so far).
231 232 233 234 235 236 237 238 239
        LDR     r3, =ZeroPage
        ADR     lr, %FT65
        ARMop   MMU_ChangingEntry,EQ,tailcall,r3         ; Clean cache & TLB
        ARMop   MMU_ChangingUncachedEntry,NE,tailcall,r3 ; Clean TLB
65
        MOV     r0, r5
        B       %BT10

70
240
        CLRV
Neil Turton's avatar
Neil Turton committed
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
        EXIT

80
        TST     r0, #alter_cacheable    ; If we haven't changed any cacheability stuff then
        BEQ     %FT90                   ;   just return error.

        AND     lr, r0, #all,wanted             ; Get wanted flags.
        LDMIA   sp, {r0,r1,r3}                  ; Get back original flags, pointer and count.
        ORR     r0, r0, lr, LSR #given-wanted   ; Wanted fields are now also given as we have done the conversion.
        BIC     r0, r0, #all:SHL:11             ; Clear wanted flags, we only want to change cacheability.
        EOR     r0, r0, #cacheable_bit          ; If we made them uncacheable then make them cacheable again & v.v.
        SUB     r2, r3, r2
        SUBS    r2, r2, #1              ; Change back the entries we have changed up to (but excluding) the error entry.
        BLNE    MemoryConvert
90
        ADRL    r0, ErrorBlock_BadAddress
95
258
        STR     r0, [sp, #Proc_RegOffset+0]
Neil Turton's avatar
Neil Turton committed
259 260 261
        SETV
        EXIT

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
   [ ChocolateAMB
;
;  entry: r3,r4,r5 = provided PN,LA,PA triple for entry to make honest (at least one given)
;         r0 bits flag which of PN,LA,PA are given
;  exit:  mapping made honest (as if not lazily mapped) if necessary
handle_AMBHonesty  ROUT
        Push    "r0, r3-r5, lr"
        TST     r0, #logical,given
        BEQ     %FT10
        MOV     r0, r4
        BL      AMB_MakeHonestLA
        B       %FT90
10
        TST     r0, #ppn,given
        BEQ     %FT20
15
        MOV     r0, r3
        BL      AMB_MakeHonestPN
        B       %FT90
20
        TST     r0, #physical,given
        BEQ     %FT90
        Push    "r7, r9-r11"
Jeffrey Lee's avatar
Jeffrey Lee committed
285
        LDR     r14, =ZeroPage
286 287 288 289 290 291 292 293 294
        LDR     r7, [r14, #MaxCamEntry]
        BL      physical_to_ppn
        Pull    "r7, r9-r11"
        BCC     %BT15
90
        Pull    "r0, r3-r5, pc"

   ] ;ChocolateAMB

Neil Turton's avatar
Neil Turton committed
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

;----------------------------------------------------------------------------------------
; ppn_to_logical
;
;       In:     r3 = page number
;               r5 = physical address if given
;               r6 = CamEntriesPointer
;               r7 = MaxCamEntry
;
;       Out:    r9 corrupted
;               CC => r4 = logical address
;               CS => invalid page number
;
;       Convert physical page number to logical address.
;
ppn_to_logical
        CMP     r7, r3                  ; Validate page number.
Kevin Bracey's avatar
Kevin Bracey committed
312 313 314
 [ No26bitCode
        BCC     meminfo_returncs        ; Invalid so return C set.
 |
Neil Turton's avatar
Neil Turton committed
315
        ORRCCS  pc, lr, #C_bit          ; Invalid so return C set.
Kevin Bracey's avatar
Kevin Bracey committed
316
 ]
Neil Turton's avatar
Neil Turton committed
317 318 319 320 321 322

        LDR     r4, [r6, r3, LSL #3]    ; If valid then lookup logical address.
        TST     r0, #physical,given     ; If physical address was given then
        LDRNE   r9, =&FFF
        ANDNE   r9, r5, r9              ;   mask off page offset
        ORRNE   r4, r4, r9              ;   and combine with logical address.
Kevin Bracey's avatar
Kevin Bracey committed
323 324 325 326
 [ No26bitCode
        CLC
        MOV     pc, lr
 |
Neil Turton's avatar
Neil Turton committed
327
        BICS    pc, lr, #C_bit          ; Return C clear.
Kevin Bracey's avatar
Kevin Bracey committed
328
 ]
Neil Turton's avatar
Neil Turton committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349


;----------------------------------------------------------------------------------------
; logical_to_physical
;
;       In:     r4 = logical address
;               r8 = L2PT
;
;       Out:    r9 corrupted
;               CC => r5 = physical address
;               CS => invalid logical address, r5 corrupted
;
;       Convert logical address to physical address.
;
logical_to_physical
        MOV     r9, r4, LSR #12         ; r9 = logical page number
        ADD     r9, r8, r9, LSL #2      ; r9 -> L2PT entry for logical address
        MOV     r5, r9, LSR #12         ; r5 = page offset to L2PT entry for logical address
        LDR     r5, [r8, r5, LSL #2]    ; r5 = L2PT entry for L2PT entry for logical address
        EOR     r5, r5, #2_10           ; Check for valid page.
        TST     r5, #3
Kevin Bracey's avatar
Kevin Bracey committed
350 351 352
 [ No26bitCode
        BNE     meminfo_returncs
 |
Neil Turton's avatar
Neil Turton committed
353
        ORRNES  pc, lr, #C_bit
Kevin Bracey's avatar
Kevin Bracey committed
354
 ]
Neil Turton's avatar
Neil Turton committed
355 356 357 358

        LDR     r5, [r9]                ; r5 = L2PT entry for logical address
        EOR     r5, r5, #2_10           ; Check for valid page.
        TST     r5, #3
Kevin Bracey's avatar
Kevin Bracey committed
359 360 361
 [ No26bitCode
        BNE     meminfo_returncs
 |
Neil Turton's avatar
Neil Turton committed
362
        ORRNES  pc, lr, #C_bit
Kevin Bracey's avatar
Kevin Bracey committed
363
 ]
Neil Turton's avatar
Neil Turton committed
364 365 366 367 368

        LDR     r9, =&FFF               ; Valid so
        BIC     r5, r5, r9              ;   mask off bits 0-11,
        AND     r9, r4, r9              ;   get page offset from logical page
        ORR     r5, r5, r9              ;   combine with physical page address.
Kevin Bracey's avatar
Kevin Bracey committed
369 370 371 372
 [ No26bitCode
        CLC
        MOV     pc, lr
 |
Neil Turton's avatar
Neil Turton committed
373
        BICS    pc, lr, #C_bit
Kevin Bracey's avatar
Kevin Bracey committed
374
 ]
Neil Turton's avatar
Neil Turton committed
375

Jeffrey Lee's avatar
Jeffrey Lee committed
376 377
meminfo_returncs_pullr5
        Pull    "r5"
Kevin Bracey's avatar
Kevin Bracey committed
378 379 380
meminfo_returncs
        SEC
        MOV     pc, lr
Neil Turton's avatar
Neil Turton committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394

;----------------------------------------------------------------------------------------
; physical_to_ppn
;
;       In:     r5 = physical address
;               r7 = MaxCamEntry
;
;       Out:    r9-r11 corrupted
;               CC => r3 = page number
;               CS => invalid physical address, r3 corrupted
;
;       Convert physical address to physical page number.
;
physical_to_ppn ROUT
Jeffrey Lee's avatar
Jeffrey Lee committed
395
        Push    "r5"
Jeffrey Lee's avatar
Jeffrey Lee committed
396
        LDR     r9, =ZeroPage+PhysRamTable
Neil Turton's avatar
Neil Turton committed
397
        MOV     r3, #0                  ; Start at page 0.
398
        MOV     r5, r5, LSR #12
Neil Turton's avatar
Neil Turton committed
399 400
10
        CMP     r7, r3                  ; Stop if we run out of pages
Jeffrey Lee's avatar
Jeffrey Lee committed
401
        BCC     meminfo_returncs_pullr5
Neil Turton's avatar
Neil Turton committed
402 403

        LDMIA   r9!, {r10,r11}          ; Get start address and size of next block.
404 405
        SUB     r10, r5, r10, LSR #12   ; Determine if given address is in this block.
        CMP     r10, r11, LSR #12
Neil Turton's avatar
Neil Turton committed
406 407 408
        ADDCS   r3, r3, r11, LSR #12    ; Move on to next block.
        BCS     %BT10

Jeffrey Lee's avatar
Jeffrey Lee committed
409 410
        Pull    "r5"

411
        ADD     r3, r3, r10
Kevin Bracey's avatar
Kevin Bracey committed
412 413
        CLC
        MOV     pc, lr
Neil Turton's avatar
Neil Turton committed
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444


;----------------------------------------------------------------------------------------
; Symbols used in MemoryPhysSize and MemoryReadPhys
;

; Shifts to determine number of bytes/words to allocate in table.
BitShift        *       10
ByteShift       *       BitShift + 3
WordShift       *       ByteShift + 2

; Bit patterns for different types of memory.
NotPresent      *       &00000000
DRAM_Pattern    *       &11111111
VRAM_Pattern    *       &22222222
ROM_Pattern     *       &33333333
IO_Pattern      *       &44444444
NotAvailable    *       &88888888


;----------------------------------------------------------------------------------------
; MemoryPhysSize
;
;       In:     r0 = 6 (reason code with flag bits 8-31 clear)
;
;       Out:    r1 = table size (in bytes)
;               r2 = page size (in bytes)
;
;       Returns information about the memory arrangement table.
;
MemoryPhysSize
445
 [ HAL
446
        Entry   "r0-r1,r3,sb,ip"
447
        AddressHAL
448 449
        MOV     r0, #PhysInfo_GetTableSize
        ADD     r1, sp, #4
450 451
        CallHAL HAL_PhysInfo
        MOV     r2, #4*1024
452
        CLRV
453 454
        EXIT
 |
Neil Turton's avatar
Neil Turton committed
455 456 457
        MOV     r1, #PhysSpaceSize :SHR: ByteShift
        MOV     r2, #4*1024
        MOV     pc, lr
458
 ]
Neil Turton's avatar
Neil Turton committed
459 460 461 462 463 464 465 466 467 468 469 470 471 472


;----------------------------------------------------------------------------------------
; MemoryReadPhys
;
;       In:     r0 = 7 (reason code with flag bits 8-31 clear)
;               r1 -> memory arrangement table to be filled in
;
;       Out:    r1 -> filled in memory arrangement table
;
;       Returns the physical memory arrangement table in the given block.
;
MemoryReadPhys  ROUT

473 474
        Entry   "r0-r12"
        AddressHAL
475 476 477
        MOV     r0, #PhysInfo_WriteTable
        SUB     sp, sp, #8
        MOV     r2, sp
478
        CallHAL HAL_PhysInfo            ; fills in everything except DRAM
479
        LDR     r0, [sp], #4
480 481 482 483 484 485 486 487
        LDR     r11, [sp], #4

        ; r0 to r11 is DRAM or not present.
        LDR     r1, [sp, #4]            ; Get table address back
        ADD     r1, r1, r0, LSR #ByteShift
        MOV     r2, r0                  ; Current physical address.
        MOV     r3, #0                  ; Next word to store in table.
        MOV     r4, #32                 ; How much more we have to shift r3 before storing it.
488 489
        LDR     r6, =ZeroPage+CamEntriesPointer
        LDR     r7, [r6]
490
        ADD     r7, r7, #4              ; Point to PPL entries.
491 492 493 494 495
        LDR     r8, [r6, #MaxCamEntry-CamEntriesPointer]
        MOV     r5, #0                  ; last block address processed + 1
        Push    "r5"

        ; Ugly logic to process PhysRamTable entries in address order instead of physical page order
496
10
497 498 499 500 501 502 503 504
        Pull    "r12"
        MVN     lr, #0
        MOV     r5, #0                  ; Current page number.
        Push    "r5,lr"
        LDR     r6, =ZeroPage+PhysRamTable
        MOV     r10, #0
11
        ADD     r5, r5, r10, LSR #12
505
        LDMIA   r6!, {r9,r10}           ; Get physical address and size of next block.
506 507
        CMP     r10, #0
        BEQ     %FT12
508 509 510

        CMP     r9, r0                  ; If not DRAM then
        CMPHS   r11, r9
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
        BLO     %BT11                   ; try next block.

        CMP     r9, r12                 ; have we processed this entry?
        CMPHS   lr, r9                  ; is it the lowest one we've seen?
        BLO     %BT11                   ; yes, try the next
        ; This is the best match so far
        STMIA   sp, {r5,r6}             ; Remember page number & details ptr
        MOV     lr, r9                  ; Remember base address
        B       %BT11
12
        Pull    "r5,r6"
        CMP     r6, #-1                 ; did we find anything?
        BEQ     %FT40
        LDMDB   r6,{r9,r10}
        ADD     r12, r9, #1
        Push    "r12"                   ; Remember that we've processed up to here

        ; Now process this entry
        MOV     r10, r10, LSR #12
        ADD     r10, r9, r10, LSL #12   ; Add amount of unused space between current and start of block.
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
        SUB     r10, r10, r2            ; size = size + (physaddr - current)
20
        SUBS    r4, r4, #4              ; Reduce shift.
        MOVCS   r3, r3, LSR #4          ; If more space in current word then shift it.
        STRCC   r3, [r1], #4            ; Otherwise, store current word
        MOVCC   r3, #0                  ;   and start a new one.
        MOVCC   r4, #28

        CMP     r2, r9                  ; If not reached start of block then page is not present.
        ORRCC   r3, r3, #(NotPresent :OR: NotAvailable) :SHL: 28
        BCC     %FT30
        LDR     lr, [r7, r5, LSL #3]    ; Page is there so get PPL and determine if it's available or not.
        TST     lr, #PageFlags_Unavailable
        ORREQ   r3, r3, #DRAM_Pattern :SHL: 28
        ORRNE   r3, r3, #(DRAM_Pattern :OR: NotAvailable) :SHL: 28
        ADD     r5, r5, #1              ; Increment page count.
30
        ADD     r2, r2, #&1000          ; Increase current address.
        SUBS    r10, r10, #&1000        ; Decrease size of block.
        BGT     %BT20                   ; Stop if no more block left.

552
        B       %BT10
553

554
40
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
        TEQ     r3, #0                          ; If not stored last word then
        MOVNE   r3, r3, LSR r4                  ;   put bits in correct position
        ADDNE   r2, r2, r4, LSL #BitShift       ;   adjust current address
        RSBNE   r4, r4, #32                     ;   rest of word is not present
        LDRNE   lr, =NotPresent :OR: NotAvailable
        ORRNE   r3, r3, lr, LSL r4
        STRNE   r3, [r1], #4                    ;   and store word.

        ; End of last block of DRAM to r11 is not present.
        MOV     r6, r0
        ADD     lr, r11, #1
        RSBS    r2, r2, lr
        MOVNE   r0, r1
        LDRNE   r1, =NotPresent :OR: NotAvailable
        MOVNE   r2, r2, LSR #ByteShift
        BLNE    memset

        ; If softloaded (ie ROM image is wholely within DRAM area returned
        ; by HAL_PhysInfo), mark that as unavailable DRAM.
Jeffrey Lee's avatar
Jeffrey Lee committed
574
        LDR     r0, =ZeroPage
575 576 577 578 579 580 581 582 583 584
        LDR     r0, [r0, #ROMPhysAddr]
        LDR     r1, [sp, #4]
        CMP     r0, r6
        ADDHS   lr, r0, #OSROM_ImageSize*1024
        SUBHS   lr, lr, #1
        CMPHS   r11, lr
        ADDHS   r0, r1, r0, LSR #ByteShift
        LDRHS   r1, =DRAM_Pattern :OR: NotAvailable
        MOVHS   r2, #(OSROM_ImageSize*1024) :SHR: ByteShift
        BLHS    memset
Neil Turton's avatar
Neil Turton committed
585

586
        CLRV
Neil Turton's avatar
Neil Turton committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
        EXIT


fill_words
        STR     r3, [r1], #4
        SUBS    r2, r2, #1
        BNE     fill_words
        MOV     pc, lr


;----------------------------------------------------------------------------------------
; MemoryAmounts
;
;       In:     r0 = flags
;                       bit     meaning
;                       0-7     8 (reason code)
603
;                       8-11    1=return amount of DRAM (excludes any soft ROM)
Neil Turton's avatar
Neil Turton committed
604 605 606
;                               2=return amount of VRAM
;                               3=return amount of ROM
;                               4=return amount of I/O space
607
;                               5=return amount of soft ROM (ROM loaded into hidden DRAM)
Neil Turton's avatar
Neil Turton committed
608 609 610 611 612 613 614 615
;                       12-31   reserved (set to 0)
;
;       Out:    r1 = number of pages of the specified type of memory
;               r2 = page size (in bytes)
;
;       Return the amount of the specified type of memory.
;
MemoryAmounts   ROUT
616
        Entry   "r3"
Neil Turton's avatar
Neil Turton committed
617

618
 [ HAL
619
        BICS    lr, r0, #&FF            ; Get type of memory required (leave bits 12-31, non-zero => error).
620 621 622 623 624 625 626 627 628
        CMP     lr, #6:SHL:8
        ADDCC   pc, pc, lr, LSR #8-2
        NOP
        B       %FT99                   ; Don't understand 0 (so the spec says).
        B       %FT10                   ; DRAM
        B       %FT20                   ; VRAM
        B       %FT30                   ; ROM
        B       %FT40                   ; I/O
        B       %FT50                   ; Soft ROM
Kevin Bracey's avatar
Kevin Bracey committed
629

630 631
10
        LDR     r1, =ZeroPage
632 633
        LDR     r3, [r1, #VideoSizeFlags]
        TST     r3, #OSAddRAM_IsVRAM
634 635 636 637 638 639 640 641
        MOVNE   r3, r3, LSR #12         ; Extract size from flags when genuine VRAM
        MOVNE   r3, r3, LSL #12
        MOVEQ   r3, #0
        LDR     r1, [r1, #RAMLIMIT]
        SUB     r1, r1, r3              ; DRAM = RAMLIMIT - VRAMSize
        B       %FT97
20
        LDR     r1, =ZeroPage
642 643
        LDR     r1, [r1, #VideoSizeFlags]
        TST     r1, #OSAddRAM_IsVRAM
644 645 646 647 648
        MOVNE   r1, r1, LSR #12
        MOVNE   r1, r1, LSL #12         ; VRAM = VRAMSize
        MOVEQ   r1, #0
        B       %FT97
30
649 650 651 652 653 654 655
        Push    "r0, sb, ip"
        AddressHAL
        MOV     r0, #PhysInfo_HardROM
        SUB     sp, sp, #8
        MOV     r2, sp
        CallHAL HAL_PhysInfo
        LDMIA   sp!, {r0-r1}
656 657
        SUBS    r1, r1, r0
        ADDNE   r1, r1, #1              ; ROM = ROMPhysTop + 1 - ROMPhysBot
658
        Pull    "r0, sb, ip"
659 660 661 662 663 664 665 666
        B       %FT97
40
        LDR     r1, =ZeroPage
        LDR     r1, [r1, #IOAllocLimit]
        LDR     r3, =IO
        SUB     r1, r3, r1              ; IO = IO ceiling - IO floor
        B       %FT97
50
667 668
        Push    "r0"
        MOV     r0, #8
669
        SWI     XOS_ReadSysInfo         ; Are we softloaded?
670 671
        Pull    "r0"
        AND     r1, r1, r2
672 673 674 675
        ANDS    r1, r1, #1:SHL:4        ; Test OS-runs-from-RAM flag
        MOVNE   r1, #OSROM_ImageSize*1024
        B       %FT97
97
676 677
        MOV     r1, r1, LSR #12         ; Return as number of pages.
        MOV     r2, #4*1024             ; Return page size.
678
        CLRV
679
        EXIT
680
99
681
        ADRL    r0, ErrorBlock_BadParameters
682 683 684
      [ International
        BL      TranslateError
      |
685
        SETV
686
      ]
687
        EXIT
688
 |
Neil Turton's avatar
Neil Turton committed
689 690 691
        BICS    lr, r0, #&FF            ; Get type of memory required (leave bits 12-31, non-zero => error).
        BEQ     %FT30                   ; Don't understand 0 (so the spec says).

692 693 694 695 696 697 698 699 700 701 702 703 704
        TEQ     lr, #5:SHL:8            ; Check for soft ROM
        BNE     %FT10
        LDR     r1, =L1PT
        MOV     r2, #ROM
        ADD     r1, r1, r2, LSR #(20-2)   ; L1PT address for ROM
        LDR     r2, [r1]
        MOV     r2, r2, LSR #12
        TEQ     r2, #PhysROM :SHR: 12     ; see if we have hard or soft ROM
        MOVEQ   r1, #0                    ; no soft ROM
        MOVNE   r1, #OSROM_ImageSize*1024 ; this much soft ROM
        B       %FT20

10
Neil Turton's avatar
Neil Turton committed
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
        TEQ     lr, #4:SHL:8            ; Check for IO space.
        LDREQ   r1, =136*1024*1024      ; Just return 136M (includes VIDC and EASI space).
        BEQ     %FT20

        TEQ     lr, #3:SHL:8            ; Check for ROM.
        LDREQ   r1, =OSROM_ImageSize*1024
        BEQ     %FT20

        TEQ     lr, #2:SHL:8            ; Check for VRAM.
        MOVEQ   r1, #0                  ; Return amount of VRAM.
        LDREQ   r1, [r1, #VRAMSize]
        BEQ     %FT20

        TEQ     lr, #1:SHL:8            ; Check for DRAM.
        BNE     %FT30
        MOV     r1, #0
        LDR     lr, [r1, #RAMLIMIT]
        LDR     r1, [r1, #VRAMSize]
        SUB     r1, lr, r1              ; Return amount of RAM - amount of VRAM.

20
        MOV     r1, r1, LSR #12         ; Return as number of pages.
        MOV     r2, #4*1024             ; Return page size.
        EXIT

30
        ADRL    r0, ErrorBlock_BadParameters
        SETV
        EXIT
734
 ]
Neil Turton's avatar
Neil Turton committed
735 736 737 738 739 740 741 742 743 744 745


;----------------------------------------------------------------------------------------
; MemoryIOSpace
;
;       In:     r0 = 9 (reason code with flag bits 8-31 clear)
;               r1 = controller ID
;                       bit     meaning
;                       0-7     controller sequence number
;                       8-31    controller type:
;                               0 = EASI card access speed control
Kevin Bracey's avatar
Kevin Bracey committed
746
;                               1 = EASI space(s)
Neil Turton's avatar
Neil Turton committed
747 748
;                               2 = VIDC1
;                               3 = VIDC20
Kevin Bracey's avatar
Kevin Bracey committed
749 750
;                               4 = S space (IOMD,podules,NICs,blah blah)
;                               5 = Extension ROM(s)
751 752 753 754 755 756
;                               6 = Tube ULA
;                               7-31 = Reserved (for us)
;                               32 = Primary ROM
;                               33 = IOMD
;                               34 = FDC37C665/SMC37C665/82C710/SuperIO/whatever
;                               35+ = Reserved (for ROL)
Neil Turton's avatar
Neil Turton committed
757 758 759 760 761
;
;       Out:    r1 = controller base address or 0 if not present
;
;       Return the location of the specified controller.
;
Kevin Bracey's avatar
Kevin Bracey committed
762 763 764 765 766 767

 [ HAL
MemoryIOSpace   ROUT
        Entry   "r0,r2,r3,sb,ip"
        AddressHAL
        CallHAL HAL_ControllerAddress
Kevin Bracey's avatar
Kevin Bracey committed
768 769 770 771 772
        CMP     r0, #-1
        MOVNE   r1, r0
        ADREQL  r0, ErrorBlock_BadParameters
        STREQ   r0, [sp, #0]
        SETV    EQ
Kevin Bracey's avatar
Kevin Bracey committed
773 774
        EXIT
 |
Neil Turton's avatar
Neil Turton committed
775
MemoryIOSpace   ROUT
776
        Entry   "r2"
Neil Turton's avatar
Neil Turton committed
777 778 779

        AND     r2, r1, #&FF            ; Get sequence number.
        MOV     r1, r1, LSR #8          ; Get controller type.
Kevin Bracey's avatar
Kevin Bracey committed
780 781 782 783
        CMP     r1, #6                  ; Make sure it's in range.
        ADRCSL  r0, ErrorBlock_BadParameters
        SETV    CS
        EXIT    CS
Neil Turton's avatar
Neil Turton committed
784 785 786 787

        ADR     lr, controller_types
        LDR     r1, [lr, r1, LSL #2]    ; Get base address or offset to table.
        TEQ     r1, #0                  ; If not present or
Kevin Bracey's avatar
Kevin Bracey committed
788 789
        CMPNE   r1, #1024               ;    not offset to table then
        EXIT    GE                      ;    return.
Neil Turton's avatar
Neil Turton committed
790 791 792 793 794 795 796 797 798 799 800 801 802

        ADD     lr, lr, r1              ; Point to table indexed by sequence number.
        LDR     r1, [lr], #4            ; Get sequence number limit.
        CMP     r2, r1                  ; Make sure it's in range.
        BCS     %FT20
        LDR     r1, [lr, r2, LSL #2]    ; Get base address.
        EXIT

controller_types
        DCD     IOMD_Base + IOMD_ECTCR  ; Expansion card timing control.
        DCD     easi_space_table - controller_types
        DCD     0
        DCD     VIDC
Kevin Bracey's avatar
Kevin Bracey committed
803 804
        DCD     IOMD_Base
        DCD     0
Neil Turton's avatar
Neil Turton committed
805 806 807 808 809 810 811 812 813 814 815

easi_space_table
        DCD     8                       ; Maximum of 8 expansion cards.
        DCD     PhysSpace + IOMD_EASI_Base0
        DCD     PhysSpace + IOMD_EASI_Base1
        DCD     PhysSpace + IOMD_EASI_Base2
        DCD     PhysSpace + IOMD_EASI_Base3
        DCD     PhysSpace + IOMD_EASI_Base4
        DCD     PhysSpace + IOMD_EASI_Base5
        DCD     PhysSpace + IOMD_EASI_Base6
        DCD     PhysSpace + IOMD_EASI_Base7
Kevin Bracey's avatar
Kevin Bracey committed
816
 ] ; HAL
Neil Turton's avatar
Neil Turton committed
817

818 819 820
;----------------------------------------------------------------------------------------
; MemoryFreePoolLock
;
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
;
;       In:     r0 bits 0..7  = 10 (reason code 10)
;               r0 bit  8     = 1 if call is by Wimp (reserved for Acorn use), 0 otherwise
;               r0 bits 9..31 reserved (must be 0)
;               r1 = 0  to resume any background actions that may manipulate FreePool mapping
;                       (currently, this is just VRAMRescue)
;                  = 1  to suspend any background actions that may manipulate FreePool mapping
;                  all other values reserved (undefined behaviour)
;
;       Out:    r1 = previous state (1=suspended, 0=not suspended)
;
; A suspend call from the Wimp will be taken to mean that the whole FreePool is locked, and
; memory cannot be moved (supports Wimp_ClaimFreeMemory)
;
; VRAM rescue doesn't happen in this Kernel, but we still support the call for the Wimp.
;
MemoryFreePoolLock ROUT
        Push    "r2,r3,lr"
Jeffrey Lee's avatar
Jeffrey Lee committed
839
        LDR     r3,=ZeroPage
840 841 842 843 844
        LDRB    lr,[r3,#VRAMRescue_control]
        TEQ     r1,#0
        BNE     %FT10
;flush TLB(s) for resume - needed for Wimp resume, precaution for other - no cache flush
;since Free Pool is uncached
845 846
 [ HAL
        Push    "r0"
Jeffrey Lee's avatar
Jeffrey Lee committed
847
        ARMop   TLB_InvalidateAll,,,r3
848 849
        Pull    "r0"
 |
850
        ARM_flush_TLB r2
851
 ]
852 853 854 855 856 857 858 859 860 861 862 863
10
        TST     r0,#&100                    ;is it Wimp?
        MOVEQ   r2,#VRRc_suspend
        MOVNE   r2,#VRRc_wimp_lock
        TEQ     r1,#0
        AND     r1,lr,r2                    ;previous state
        BICEQ   lr,lr,r2
        ORRNE   lr,lr,r2
        STRB    lr,[r3,#VRAMRescue_control] ;set/clear relevant bit
        TEQ     r1,#0
        MOVNE   r1,#1
        Pull    "r2,r3,pc"
864 865 866 867 868 869 870 871 872 873 874

;----------------------------------------------------------------------------------------
;PCImapping - reserved for Acorn use (PCI manager)
;
; See code on Ursula branch


;----------------------------------------------------------------------------------------
;RecommendPage
;
;       In:     r0 bits 0..7  = 12 (reason code 12)
875 876
;               r0 bit 8 = 1 if region must be DMAable
;               r0 bits 9..31 = 0 (reserved flags)
877 878 879 880 881 882 883 884 885
;               r1 = size of physically contiguous RAM region required (bytes)
;               r2 = log2 of required alignment of base of region (eg. 12 = 4k, 20 = 1M)
;
;       Out:    r3 = page number of first page of recommended region that could be
;                    grown as specific pages by dynamic area handler (only guaranteed
;                    if grow is next page claiming operation)
;        - or error if not possible (eg too big, pages unavailable)
;
RecommendPage ROUT
886
        Push    "r0-r2,r4-r11,lr"
887
        CMP     r2,#30
888 889 890
        BHI     RP_failed         ;refuse to look for alignments above 1G
        ANDS    r11,r0,#1:SHL:8   ;convert flag into something usable in the loop
        MOVNE   r11,#OSAddRAM_NoDMA
891 892 893 894 895 896 897 898 899 900 901
;
        ADD     r1,r1,#&1000
        SUB     r1,r1,#1
        MOV     r1,r1,LSR #12
        MOVS    r1,r1,LSL #12     ;size rounded up to whole no. of pages
;
        CMP     r2,#12
        MOVLO   r2,#12            ;log2 alignment must be at least 12 (4k pages)
        MOV     r0,#1
        MOV     r4,r0,LSL r2      ;required alignment-1
;
Jeffrey Lee's avatar
Jeffrey Lee committed
902
        LDR     r0,=ZeroPage+PhysRamTable
903
        MOV     r3,#0            ;page number, starts at 0
Jeffrey Lee's avatar
Jeffrey Lee committed
904
        LDR     r5,=ZeroPage+CamEntriesPointer
905 906 907 908 909 910 911 912 913
        LDR     r5,[r5]
        ADD     r5,r5,#4         ; [r5,<page no.>,LSL #3] addresses flags word in CAM
        LDMIA   r0!,{r7,r8}      ;address,size of video chunk (skip this one)
;
RP_nextchunk
        ADD     r3,r3,r8,LSR #12 ;page no. of first page of next chunk
        LDMIA   r0!,{r7,r8}      ;address,size of next physical chunk
        CMP     r8,#0
        BEQ     RP_failed
914 915
        TST     r8,r11           ;ignore non-DMA regions if bit 8 of R0 was set
        BNE     RP_nextchunk
916
;
917
        MOV     r8,r8,LSR #12
918
        ADD     r6,r7,r4
919
        MOV     r8,r8,LSL #12
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
        SUB     r6,r6,#1         ;round up
        MOV     r6,r6,LSR r2
        MOV     r6,r6,LSL r2
        SUB     r6,r6,r7         ;adjustment to first address of acceptable alignment
        CMP     r6,r8
        BHS     RP_nextchunk     ;negligible chunk
        ADD     r7,r3,r6,LSR #12 ;first page number of acceptable alignment
        SUB     r9,r8,r6         ;remaining size of chunk
;
;find first available page
RP_nextpage
        CMP     r9,r1
        BLO     RP_nextchunk
        LDR     r6,[r5,r7,LSL #3]  ;page flags from CAM
        ;must not be marked Unavailable or Required
        TST     r6,#PageFlags_Unavailable :OR: PageFlags_Required
        BEQ     RP_checkotherpages
RP_nextpagecontinue
        CMP     r9,r4
        BLS     RP_nextchunk
        ADD     r7,r7,r4,LSR #12   ;next page of suitable alignment
        SUB     r9,r9,r4
        B       RP_nextpage
;
RP_checkotherpages
        ADD     r10,r7,r1,LSR #12
        SUB     r10,r10,#1         ;last page required
RP_checkotherpagesloop
        LDR     r6,[r5,r10,LSL #3] ;page flags from CAM
        TST     r6,#PageFlags_Unavailable :OR: PageFlags_Required
        BNE     RP_nextpagecontinue
        SUB     r10,r10,#1
        CMP     r10,r7
        BHI     RP_checkotherpagesloop
;
;success!
;
        MOV     r3,r7
958
        Pull    "r0-r2,r4-r11,pc"
959 960 961 962 963 964

RP_failed
        MOV     r3,#0
        ADR     r0,RP_error
        SETV
        STR     r0,[sp]
965
        Pull    "r0-r2,r4-r11,pc"
966 967 968 969 970 971

RP_error
        DCD     0
        DCB     "No chunk available (OS_Memory 12)",0
        ALIGN

972 973 974 975 976
;----------------------------------------------------------------------------------------
;MapIOpermanent - map IO space (if not already mapped) and return logical address
;
;       In:     r0 bits 0..7  = 13 (reason code 13)
;               r0 bit  8     = 1 to map bufferable space (0 is normal, non-bufferable)
977 978 979
;               r0 bit  9     = 1 to map cacheable space (0 is normal, non-cacheable)
;               r0 bits 10..12 = 0 (reserved for cache policy)
;               r0 bits 13..15 = 0 (reserved flags)
Kevin Bracey's avatar
Kevin Bracey committed
980
;               r0 bit  16    = 1 to doubly map
981 982 983 984
;               r0 bit  17    = 1 if access privileges specified
;               r0 bits 18..23 = 0 (reserved flags)
;               r0 bits 24..27 = access privileges (if bit 17 set)
;               r0 bits 28..31 = 0 (reserved flags)
985 986 987 988 989 990 991 992
;               r1 = physical address of base of IO space required
;               r2 = size of IO space required (bytes)
;
;       Out:    r3 = logical address of base of IO space
;        - or error if not possible (no room)
;
MapIOpermanent ROUT
        Push    "r0-r2,r12,lr"
Kevin Bracey's avatar
Kevin Bracey committed
993
        MOV     lr, r0
994
        TST     lr, #1:SHL:8        ;test bufferable bit
995 996
        MOVNE   r0, #L1_B
        MOVEQ   r0, #0
Robert Sprowson's avatar
Robert Sprowson committed
997
        TST     lr, #1:SHL:9        ;test cacheable bit
998
        ORRNE   r0, r0, #L1_C
Kevin Bracey's avatar
Kevin Bracey committed
999 1000
        TST     lr, #1:SHL:16
        ORRNE   r0, r0, #MapInFlag_DoublyMapped
1001 1002 1003 1004 1005 1006
        TST     lr, #1:SHL:17
        ANDNE   lr, lr, #2_1111:SHL:24
        ADRNEL  r12, PPLTransL1
        LDRNE   r12, [r12, lr, LSR #22]
        ORRNE   r0, r0, #MapInFlag_APSpecified
        ORRNE   r0, r0, r12
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
        BL      RISCOS_MapInIO
        MOV     r3, r0
        CMP     r3, #0              ;MOV,CMP rather than MOVS to be sure to clear V
        Pull    "r0-r2,r12,pc",NE
        ADR     r0, MIp_error
        SETV
        STR     r0, [sp]
        Pull    "r0-r2,r12,pc"

MIp_error
        DCD     0
        DCB     "No room for IO space (OS_Memory 13)",0
        ALIGN

;----------------------------------------------------------------------------------------
;AccessPhysAddr - claim temporary access to given physical address (in fact,
;                 controls access to the 1Mb aligned space containing the address)
;                 The access remains until the next AccessPhysAddr or until a
;                 ReleasePhysAddr (although interrupts or subroutines may temporarily
;                 make their own claims, but restore on Release before returning)
;
;       In:     r0 bits 0..7  = 14 (reason code 14)
;               r0 bit  8     = 1 to map bufferable space, 0 for unbufferable
;               r0 bits 9..31 = 0 (reserved flags)
;               r1 = physical address
;
;       Out:    r2 = logical address corresponding to phys address r1
;               r3 = old state (for ReleasePhysAddr)
;
; Use of multiple accesses: it is fine to make several Access calls, and
; clean up with a single Release at the end. In this case, it is the old state
; (r3) of the *first* Access call that should be passed to Release in order to
; restore the state before any of your accesses. (The r3 values of the other
; access calls can be ignored.)
;
AccessPhysAddr ROUT
        Push    "r0,r1,r12,lr"
        TST     r0, #&100           ;test bufferable bit
        MOVNE   r0, #L1_B
        MOVEQ   r0, #0
        SUB     sp, sp, #4          ; word for old state
        MOV     r2, sp              ; pointer to word
        BL      RISCOS_AccessPhysicalAddress
        MOV     r2, r0
        Pull    r3                  ; old state
        Pull    "r0,r1,r12,pc"

;----------------------------------------------------------------------------------------
;ReleasePhysAddr - release temporary access that was claimed by AccessPhysAddr
;
;       In:     r0 bits 0..7  = 15 (reason code 15)
;               r0 bits 8..31 = 0 (reserved flags)
;               r1 = old state to restore
;
ReleasePhysAddr
        Push    "r0-r3,r12,lr"
        MOV     r0, r1
        BL      RISCOS_ReleasePhysicalAddress
        Pull    "r0-r3,r12,pc"

1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
;----------------------------------------------------------------------------------------
;
;        In:    r0 = flags
;                       bit     meaning
;                       0-7     16 (reason code)
;                       8-15    1=cursor/system/sound
;                               2=IRQ stack
;                               3=SVC stack
;                               4=ABT stack
;                               5=UND stack
;                               6=Soft CAM
;                               7=Level 1 page tables
;                               8=Level 2 page tables
;                               9=HAL workspace
;                               10=Kernel buffers
1082
;                               11=HAL uncacheable workspace
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
;                       16-31   reserved (set to 0)
;
;       Out:    r1 = base of area
;               r2 = address space allocated for area (whole number of pages)
;               r3 = actual memory used by area (whole number of pages)
;               all values 0 if not present, or incorporated into another area
;
;       Return size of various low-level memory regions
MemoryAreaInfo ROUT
        Entry   "r0"
        MOV     r1, #0
        MOV     r2, #0
        MOV     r3, #0
        MOV     lr, r0, LSR #8
        AND     lr, lr, #&FF
        CMP     lr, #(MAI_TableEnd - MAI_TableStart)/4
        ADDLO   pc, pc, lr, LSL #2
        B       %FT70
MAI_TableStart
        B       %FT70
        B       MAI_CursSysSound
        B       MAI_IRQStk
        B       MAI_SVCStk
        B       MAI_ABTStk
        B       MAI_UNDStk
        B       MAI_SoftCAM
        B       MAI_L1PT
        B       MAI_L2PT
        B       MAI_HALWs
        B       MAI_Kbuffs
1113
        B       MAI_HALWsNCNB
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
MAI_TableEnd

70
        ADRL    r0, ErrorBlock_BadParameters
        SETV
        STR     r0, [sp, #Proc_RegOffset+0]
        EXIT

MAI_CursSysSound
        LDR     r1, =CursorChunkAddress
        MOV     r2, #32*1024
        MOV     r3, r2
        EXIT

MAI_IRQStk
 [ IRQSTK < CursorChunkAddress :LOR: IRQSTK > CursorChunkAddress+32*1024
        LDR     r1, =IRQStackAddress
        MOV     r2, #IRQSTK-IRQStackAddress
        MOV     r3, r2
 ]
        EXIT

MAI_SVCStk
        LDR     r1, =SVCStackAddress
        MOV     r2, #SVCSTK-SVCStackAddress
        MOV     r3, r2
        EXIT

MAI_ABTStk
 [ No26bitCode
        LDR     r1, =ABTStackAddress
        MOV     r2, #ABTSTK-ABTStackAddress
        MOV     r3, r2
 ]
        EXIT

MAI_UNDStk
        LDR     r1, =UNDSTK :AND: &FFF00000
        LDR     r2, =UNDSTK :AND: &000FFFFF
        MOV     r3, r2
        EXIT

MAI_SoftCAM
Jeffrey Lee's avatar
Jeffrey Lee committed
1157
        LDR     r0, =ZeroPage
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
        LDR     r1, [r0, #CamEntriesPointer]
        LDR     r2, =CAMspace
        LDR     r3, [r0, #SoftCamMapSize]
        EXIT

MAI_L1PT
        LDR     r1, =L1PT
        MOV     r2, #16*1024
        MOV     r3, r2
        EXIT

MAI_L2PT
Jeffrey Lee's avatar
Jeffrey Lee committed
1170
        LDR     r0, =ZeroPage
1171 1172 1173 1174 1175 1176
        LDR     r1, =L2PT
        MOV     r2, #4*1024*1024
        LDR     r3, [r0, #L2PTUsed]
        EXIT

MAI_HALWs
1177
 [ HAL
Jeffrey Lee's avatar
Jeffrey Lee committed
1178
        LDR     r0, =ZeroPage
1179
        LDR     r1, =HALWorkspace
1180
        MOV     r2, #HALWorkspaceSize
1181 1182 1183 1184
        LDR     r3, [r0, #HAL_WsSize]
 ]
        EXIT

1185 1186
MAI_HALWsNCNB
 [ HAL
Jeffrey Lee's avatar
Jeffrey Lee committed
1187
        LDR     r0, =ZeroPage
1188 1189 1190 1191 1192 1193 1194 1195 1196
        LDR     r1, =HALWorkspaceNCNB
        MOV     r2, #32*1024
        LDR     r3, [r0, #HAL_Descriptor]
        LDR     r3, [r3, #HALDesc_Flags]
        ANDS    r3, r3, #HALFlag_NCNBWorkspace
        MOVNE   r3, r2
 ]
        EXIT

1197 1198 1199 1200 1201
MAI_Kbuffs
        LDR     r1, =KbuffsBaseAddress
        MOV     r2, #KbuffsMaxSize
        LDR     r3, =(KbuffsSize + &FFF) :AND: :NOT: &FFF
        EXIT
1202

1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 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 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
;----------------------------------------------------------------------------------------
;
;        In:    r0 = flags
;                       bit     meaning
;                       0-7     24 (reason code)
;                       8-31    reserved (set to 0)
;               r1 = low address (inclusive)
;               r2 = high address (exclusive)
;
;       Out:    r1 = access flags:
;               bit 0: completely readable in user mode
;               bit 1: completely writable in user mode
;               bit 2: completely readable in privileged modes
;               bit 3: completely writable in privileged modes
;               bit 4: partially readable in user mode
;               bit 5: partially writable in user mode
;               bit 6: partially readable in privileged modes
;               bit 7: partially writable in privileged modes
;               bit 8: completely physically mapped (i.e. IO memory)
;               bit 9: completely abortable (i.e. custom data abort handler)
;               bits 10,11: reserved
;               bit 12: partially physically mapped
;               bit 13: partially abortable
;               bits 14+: reserved
;
;       Return various attributes for the given memory region
CMA_Completely_UserR   * 1<<0
CMA_Completely_UserW   * 1<<1
CMA_Completely_PrivR   * 1<<2
CMA_Completely_PrivW   * 1<<3
CMA_Partially_UserR    * 1<<4
CMA_Partially_UserW    * 1<<5
CMA_Partially_PrivR    * 1<<6
CMA_Partially_PrivW    * 1<<7
CMA_Completely_Phys    * 1<<8
CMA_Completely_Abort   * 1<<9
CMA_Partially_Phys     * 1<<12
CMA_Partially_Abort    * 1<<13

CMA_CheckL2PT          * 1<<31 ; Pseudo flag used internally for checking sparse areas

; AP_ equivalents
CMA_ROM  * CMA_Partially_UserR+CMA_Partially_PrivR
CMA_Read * CMA_ROM+CMA_Partially_PrivW
CMA_Full * CMA_Read+CMA_Partially_UserW
CMA_None * CMA_Partially_PrivR+CMA_Partially_PrivW

CheckMemoryAccess ROUT
        Entry   "r0,r2-r10"
        CMP     r0, #24
        BNE     %FT99
        LDR     r10, =ZeroPage
        ; Set all the 'completely' flags, we'll clear them as we go along
        LDR     r0, =&0F0F0F0F
        ; Make end address inclusive so we don't have to worry so much about
        ; wrap around at 4G
        TEQ     r1, r2
        SUBNE   r2, r2, #1
        ; Split memory up into five main regions:
        ; * scratchspace/zeropage
        ; * application space
        ; * dynamic areas
        ; * IO memory
        ; * special areas (stacks, ROM, HAL workspace, system heap, etc.)
        ; All ranges are checked in increasing address order, so the
        ; completeness flags are returned correctly if we happen to cross from
        ; one range into another
        ; Note that application space can't currently be checked in DA block as
        ; (a) it's not linked to DAList/DynArea_AddrLookup
        ; (b) we need to manually add the abortable flag
        CMP     r1, #32*1024
        BHS     %FT10
        ; Check zero page
      [ ZeroPage = 0
        MOV     r3, #0
        MOV     r4, #16*1024
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
      |
        ; DebuggerSpace
        ASSERT  DebuggerSpace < ScratchSpace
        LDR     r3, =DebuggerSpace
        LDR     r4, =(DebuggerSpace_Size + &FFF) :AND: &FFFFF000
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
      ]
        ; Scratch space
        LDR     r3, =ScratchSpace
        MOV     r4, #16*1024
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
10
        ; Application space
        ; Note - checking AplWorkSize as opposed to AplWorkMaxSize to cope with
        ; software which creates DAs within application space (e.g. Aemulor)
        LDR     r4, [r10, #AplWorkSize]
        CMP     r1, r4
        BHS     %FT20
        LDR     r3, [r10, #AMBControl_ws]
        LDR     r3, [r3, #:INDEX:AMBFlags]
        MOV     r5, #CMA_Full
        TST     r3, #AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend
        MOV     r3, #32*1024
        ORREQ   r5, r5, #CMA_Partially_Abort
        BL      CMA_AddRange2
20
        ; Dynamic areas
        LDR     r7, [r10, #IOAllocLimit]
        CMP     r1, r7
        BHS     %FT30
        ; Look through the quick lookup table until we find a valid DANode ptr
        LDR     r6, [r10, #DynArea_ws]
        MOV     r3, r1
        ADD     r6, r6, #(:INDEX:DynArea_AddrLookup) :AND: &00FF
        ADD     r6, r6, #(:INDEX:DynArea_AddrLookup) :AND: &FF00
21
        AND     r8, r3, #DynArea_AddrLookupMask
        LDR     r9, [r6, r8, LSR #30-DynArea_AddrLookupBits]
        TEQ     r9, #0
        BNE     %FT22
        ; Nothing here, skip ahead to next block
        ADD     r3, r8, #DynArea_AddrLookupSize
        CMP     r3, r2
        BHI     %FT90 ; Hit end of search area
        CMP     r3, r7
        BLO     %BT21
        ; Hit end of DA area and wandered into IO area
        B       %FT30
22
        ; Now that we've found a DA to start from, walk through and process all
        ; the entries until we hit the system heap (or any other DAs above
        ; IOAllocLimit)
        LDR     r3, [r9, #DANode_Base]
        LDR     r6, [r9, #DANode_Flags]
        CMP     r3, r7
        BHS     %FT30
        ; Decode AP flags
        ANDS    lr, r6, #3
        MOVEQ   r5, #CMA_Full
        TEQ     lr, #1
        MOVEQ   r5, #CMA_Read
        CMP     lr, #2
        MOVEQ   r5, #CMA_None
        MOVGT   r5, #CMA_ROM
        TST     r6, #DynAreaFlags_SparseMap
        LDREQ   lr, [r9, #DANode_Size]
        LDRNE   lr, [r9, #DANode_SparseHWM] ; Use HWM as bounds when checking sparse areas
        ORRNE   r5, r5, #CMA_CheckL2PT ; ... and request L2PT check
        TST     r6, #DynAreaFlags_DoublyMapped
        ADD     r4, r3, lr
        SUBNE   r3, r3, lr
        BL      CMA_AddRange2
        LDR     r9, [r9, #DANode_Link]
        TEQ     r9, #0
        BNE     %BT22
        ; Hit the end of the list. This shouldn't happen with the current heap setup!
30
        ; IO memory
        CMP     r1, #IO
        BHS     %FT40
        MOV     r3, r1, LSR #20
        LDR     r4, [r10, #IOAllocPtr]
        MOV     r3, r3, LSL #20 ; Get MB-aligned addr of first entry to check
        CMP     r3, r4
        LDR     r7, =L1PT
        MOVLO   r3, r4 ; Skip all the unallocated regions
31
        LDR     r4, [r7, r3, LSR #20-2]
        AND     r4, r4, #L1_AP
        ; Decode page AP flags
        MOV     r5, #CMA_ROM
        CMP     r4, #AP_None*L1_APMult
        MOVEQ   r5, #CMA_None
        CMP     r4, #AP_Read*L1_APMult
        MOVEQ   r5, #CMA_Read
        CMP     r4, #AP_Full*L1_APMult
        MOVEQ   r5, #CMA_Full
        ADD     r4, r3, #1<<20
        ORR     r5, r5, #CMA_Partially_Phys
        BL      CMA_AddRange2
        CMP     r4, #IO
        MOV     r3, r4
        BNE     %BT31
40
        ; Everything else!
        LDR     r3, =HALWorkspace
        LDR     r4, [r10, #HAL_WsSize]
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
        ASSERT  IRQStackAddress > HALWorkspace
        LDR     r3, =IRQStackAddress
        LDR     r4, =IRQStackSize
        MOV     r5, #CMA_None
        BL      CMA_AddRange
        ASSERT  SVCStackAddress > IRQStackAddress
        LDR     r3, =SVCStackAddress
        LDR     r4, =SVCStackSize
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
        ASSERT  ABTStackAddress > SVCStackAddress
        LDR     r3, =ABTStackAddress
        LDR     r4, =ABTStackSize
        MOV     r5, #CMA_None
        BL      CMA_AddRange
        ASSERT  UNDStackAddress > ABTStackAddress
        LDR     r3, =UNDStackAddress
        LDR     r4, =UNDStackSize
        MOV     r5, #CMA_None
        BL      CMA_AddRange
        ASSERT  PhysicalAccess > UNDStackAddress
        LDR     r3, =L1PT + (PhysicalAccess:SHR:18)
        LDR     r3, [r3]
        TEQ     r3, #0
        BEQ     %FT50
        LDR     r3, =PhysicalAccess
        LDR     r4, =&100000
        LDR     r5, =CMA_None+CMA_Partially_Phys ; Assume IO memory mapped there
        BL      CMA_AddRange
50
        ASSERT  DCacheCleanAddress > PhysicalAccess
        LDR     r4, =DCacheCleanAddress+DCacheCleanSize
        CMP     r1, r4
        BHS     %FT60
        ; Check that DCacheCleanAddress is actually used
        Push    "r0-r2,r9"
        AddressHAL r10
        MOV     a1, #-1
        CallHAL HAL_CleanerSpace
        CMP     a1, #-1
        Pull    "r0-r2,r9"
        BEQ     %FT60
        SUB     r3, r4, #DCacheCleanSize
        MOV     r4, #DCacheCleanSize
        LDR     r5, =CMA_None+CMA_Partially_Phys ; Mark as IO, it may not be actual memory there
        BL      CMA_AddRange
60
        ASSERT  KbuffsBaseAddress > DCacheCleanAddress
        LDR     r3, =KbuffsBaseAddress
        LDR     r4, =(KbuffsSize + &FFF) :AND: &FFFFF000
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
        ASSERT  HALWorkspaceNCNB > KbuffsBaseAddress
        LDR     r3, [r10, #HAL_Descriptor]
        LDR     r3, [r3, #HALDesc_Flags]
        TST     r3, #HALFlag_NCNBWorkspace
        BEQ     %FT70
        LDR     r3, =HALWorkspaceNCNB
        LDR     r4, =32*1024
        MOV     r5, #CMA_None
        BL      CMA_AddRange
70
        ASSERT  CursorChunkAddress > HALWorkspaceNCNB
        LDR     r3, =CursorChunkAddress
        MOV     r4, #32*1024
        MOV     r5, #CMA_Read
        BL      CMA_AddRange
        ASSERT  L2PT > CursorChunkAddress
        LDR     r3, =L2PT
        MOV     r5, #CMA_None
        MOV     r4, #4*1024*1024
        ORR     r5, r5, #CMA_CheckL2PT ; L2PT contains gaps due to logical indexing
        BL      CMA_AddRange
        ASSERT  L1PT > L2PT
        LDR     r3, =L1PT
        MOV     r4, #16*1024
        MOV     r5, #CMA_None
        BL      CMA_AddRange
        ; Note that system heap needs to be checked manually due to being
        ; outside main DA address range
        ASSERT  SysHeapChunkAddress > L1PT
        LDR     r3, =SysHeapChunkAddress
        LDR     r4, [r10, #SysHeapDANode + DANode_Size]
        MOV     r5, #CMA_Full
        BL      CMA_AddRange
        ASSERT  CAM > SysHeapChunkAddress
        LDR     r3, =CAM
        LDR     r4, [r10, #SoftCamMapSize]
        MOV     r5, #CMA_None
        BL      CMA_AddRange
        ASSERT  ROM > CAM
        LDR     r3, =ROM
        LDR     r4, =OSROM_ImageSize*1024
        MOV     r5, #CMA_ROM
        BL      CMA_AddRange
        ; Finally, high processor vectors/relocated zero page
      [ ZeroPage > 0
        ASSERT  ZeroPage > ROM
        MOV     r3, r10
        LDR     r4, =16*1024
1492
        MOV     r5, #CMA_Read
1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
        BL      CMA_AddRange
      ]
90
        ; If there's anything else, we've wandered off into unallocated memory
        LDR     r3, =&0F0F0F0F
        BIC     r1, r0, r3
        CLRV
        EXIT

99
        PullEnv
        ADRL    r0, ErrorBlock_BadParameters
        SETV
        MOV     pc, lr

        ; Add range r3..r4 to attributes in r0
        ; Corrupts r8
CMA_AddRange ROUT ; r3 = start, r4 = length
        ADD     r4, r3, r4
CMA_AddRange2 ; r3 = start, r4 = end (excl.)
        LDR     r8, =&0F0F0F0F
        ; Increment r1 and exit if we hit r2
        ; Ignore any ranges which are entirely before us
        CMP     r1, r4
        MOVHS   pc, lr
        ; Check for any gap at the start, i.e. r3 > r1
        CMP     r3, r1
        BICHI   r0, r0, r8
        MOVHI   r1, r3 ; Update r1 for L2PT check code
        ; Exit if the range starts after our end point
        CMP     r3, r2
        BHI     %FT10
        ; Process the range
        TST     r5, #CMA_CheckL2PT
        BNE     %FT20
        CMP     r3, r4 ; Don't apply any flags for zero-length ranges
04      ; Note L2PT check code relies on NE condition here
        ORR     r8, r5, r8
        ORRNE   r0, r0, r5 ; Set new partial flags
        ANDNE   r0, r0, r8, ROR #4 ; Discard completion flags which aren't for this range
05
        CMP     r4, r2
        MOV     r1, r4 ; Continue search from the end of this range
        MOVLS   pc, lr
10
        ; We've ended inside this range
        MOV     r1, r0
        CLRV
        EXIT

20
        ; Check L2PT for sparse region r1..min(r2+1,r4)
        ; r4 guaranteed page aligned
        CMP     r3, r4
        BIC     r5, r5, #CMA_CheckL2PT
        BEQ     %BT05
        Push    "r2,r4,r5,r8,r9,r10,lr"
        LDR     lr, =&FFF
        CMP     r4, r2
        ADDHS   r2, r2, #4096
        BICHS   r2, r2, lr
        MOVLO   r2, r4
        ; r2 is now page aligned min(r2+1,r4)
        BIC     r4, r1, lr
        LDR     r8, =L2PT
        MOV     r10, #0
30
        BL      logical_to_physical
        ORRCC   r10, r10, #1
        ADD     r4, r4, #4096
        ORRCS   r10, r10, #2
        CMP     r4, r2
        BNE     %BT30
        CMP     r10, #2
        ; 01 -> entirely mapped
        ; 10 -> entirely unmapped
        ; 11 -> partially mapped
        Pull    "r2,r4,r5,r8,r9,r10,lr"
        BICHS   r0, r0, r8 ; Not fully mapped, clear completion flags
        BNE     %BT04 ; Partially/entirely mapped
        B       %BT05 ; Completely unmapped

Neil Turton's avatar
Neil Turton committed
1575
        END