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

; AMBControl - takes care of application memory management (for Wimp)

;Nov 95 - Started by mjs

;;; Initialisation
;
AMBControl_Init
        Push    "R0-R4,R12,LR"

        LDR     R3,=AMBmaxwork
        BL      ClaimSysHeapNode
;;;        BVS     err_cantclaim - this should not happen

;don't store ws pointer till end of initialise - service routines must
;know when initialise is not yet complete
;
        MOV     R12,R2

;block for handle array
        MOV     R3,#(AMBInitialMaxNodes:SHL:2)
        BL      ClaimSysHeapNode
;;;        BVS     err_cantclaim
        STR     R2,AMBNodeHandles

;put all handles on free list (entry 0 is used as hdr of free list)
        MOV     R0,#1
        MOV     R1,#AMBInitialMaxNodes
        STR     R1,AMBNhandles
01
        STR     R0,[R2],#4
        ADD     R0,R0,#1
        CMP     R0,R1
        BNE     %BT01
        MOV     R0,#0       ; = end of list
        STR     R0,[R2]

;block for PhysBin array
        LDR     R3,=MaxCamEntry
        LDR     R3,[R3]
        ADD     R3,R3,#1                   ;no. of RAM pages extant
        MOV     R3,R3,LSR #AMBPhysBinShift ;no. of bin entries reqd.
        STR     R3,AMBPhysBinEntries
        MOV     R3,R3,LSL #2               ;1 word per entry
        BL      ClaimSysHeapNode
;;;        BVS     err_cantclaim
        STR     R2,AMBPhysBin

;init PhysBin
        MOV     R0,#PhysRamTable
        LDR     R3,AMBPhysBin
        LDR     R4,AMBPhysBinEntries
        LDMIA   R0!,{R1,R2}             ;address,size of first physical fragment
        MOV     R2,R2,LSR #Log2PageSize ;no. pages in fragment
        B       %FT04
03
        ADD     R1,R1,#(1:SHL:(Log2PageSize+AMBPhysBinShift)) ;next bin address
        SUBS    R2,R2,#(1:SHL:AMBPhysBinShift)                ;no. pages binned
        LDMLEIA R0!,{R1,R2}             ;address,size of next physical fragment
        MOVLE   R2,R2,LSR #Log2PageSize ;no. pages in fragment
04
        STR     R1,[R3],#4
        SUBS    R4,R4,#1
        BNE     %BT03

; init anchor node stuff etc.
        MOV     R0,#0
        STR     R0,AMBNtasks
        STR     R0,AMBMappedInNode
        ADR     R1,AMBAnchorNode
        MOV     R3,R1
        STR     R0,[R1],#4  ; node id = 0 for ank node (not a real node!)
        STR     R0,[R1],#4  ; handle = 0
        STR     R3,[R1],#4  ; prev (starts -> ank node)
        STR     R3,[R1],#4  ; next (starts -> ank node)
        STR     R0,[R1],#4  ; Npages
        STR     R0,[R1],#4  ; startaddr
        STR     R0,[R1],#4  ; PPL

        MOV     R0,#AMBControl_ws
        STR     R12,[R0]           ;now initialisation is complete

        Pull    "R0-R4,R12,PC"


; OS_AMBControl SWI handler
; entry:
;   R0 = reason code (bits 0..7) and flags (bits 8..31), flags depend on reason
;   other regs. depend on reason code
; exit:
;   R0 preserved
;   other regs. depend on reason code

AMBControlSWI
        MOV     R12,#AMBControl_ws
        LDR     R12,[R12]

        AND     R11,R0,#&FF
        CMP     R11,#(reasons0-reasons1)/4
        ADDCC   PC,PC,R11,LSL #2        ;Despatch if within a suitable range
        B       reasons1
reasons0
        B       allocate     ;0
        B       deallocate   ;1
        B       growshrink   ;2
        B       mapslot      ;3
        B       readinfo     ;4
        B       reserved     ;5
        B       reserved     ;6
        B       reserved     ;7
        B       mjs_info     ;8 - system reason code, dumps info to buffer
reasons1
        ADR     R0,err_badreason
        B       SLVK_SetV


;entry: R0=8 (reason),R1 -> buffer (say 4k for up to 255 tasks)
;exit: buffer filled:
;       0   Ntasks
;       4   Handle of mapped in task (or 0)
;       8   Handle 1
;      12   Npages 1
;      16   Logical address 1
;      20   PPL 1
;      24   Handle 2
;      28   Npages 2
;      32   Logical address 2
;      36   PPL 2
;      ...
mjs_info
       Push    "R1-R7,LR"
       LDR     R2,AMBNtasks
       STR     R2,[R1],#4
       LDR     R2,AMBMappedInNode
       CMP     R2,#0
       LDRNE   R2,[R2,#AMBNode_handle]
       STR     R2,[R1],#4
       ADR     R2,AMBAnchorNode
       MOV     R7,R2
01
       LDR     R2,[R2,#AMBNode_next]
       CMP     R2,R7
       BEQ     %FT02
       LDR     R3,[R2,#AMBNode_handle]
       LDR     R4,[R2,#AMBNode_Npages]
       LDR     R5,[R2,#AMBNode_startaddr]
       LDR     R6,[R2,#AMBNode_PPL]
       STMIA   R1!,{R3-R6}
       B       %BT01
02
       Pull    "R1-R7,LR"
       B       SLVK

reserved
       ADR     R0,err_reserved
       B       SLVK_SetV

;;; errors (sod internationalisation)

;;;err_cantclaim
;;;        DCD     0
;;;        DCB     "AMBControl failed to claim workspace",0
;;;        ALIGN

err_badreason
        DCD     0
        DCB     "bad AMBControl reason code",0
        ALIGN

err_reserved
        DCD     0
        DCB     "reserved AMBControl reason code",0
        ALIGN

err_nomorehandles
        DCD     0
        DCB     "AMBControl handles exhausted",0
        ALIGN

   END