.TITLE MOSMEM - MOS STORAGE MANAGER .INSRT ../moscnf-1.sml .INSRT ../mosmac.sml .INSRT ../mostbl.sml $CNFIG .PAGE $DFSD ;DEFINE STORAGE DESCRIPTOR ENTRY .LIST MEB .ENABL ISD .GLOBL $MEMDT ;STORAGE MEMORY DESCRIPTOR TABLE .GLOBL DSCHD ;SYSTEM SCHEDULER .GLOBL $INIPL ;INITIALIZE STORAGE POOLS ROUTINE .GLOBL $GTBLK ;GET KERNEL STORAGE BLOCK .GLOBL $RLBLK ;RELEASE KERNEL STORAGE BLOCK .GLOBL $AVS ;ALLOCATE REAL STORAGE(AND WAIT) .GLOBL $FVS ;FREE REAL STORAGE .GLOBL $ALS ;ALLOCATE STORAGE(NO WAIT) .GLOBL $SCK ;STORAGE CHECK .GLOBL $MSTAT ;GET MEMORY STATISTICS .GLOBL $BLKPL ;KERNEL BLOCK POOL .GLOBL NKBLKS ;NUMBER OF KERNEL STORAGE BLOCKS .GLOBL $LOMEM, LOMEM ;BOTTOM ADDR OF STORAGE AREA .GLOBL $BTMEM, BTMEM ;BOTTOM ADDRESS OF FREE STORAGE .GLOBL $TPMEM, TPMEM ;TOP ADDRESS OF FREE STORAGE .GLOBL $FRMEM, FRMEM ;AMOUNT OF FREE MEMORY .GLOBL ENDMEM ;TOP OF USABLE AREA .GLOBL FSPACE ;START OF USABLE MEMORY .GLOBL D.SYMT ;START OF DDT SYMBOL TABLE ADDR .GLOBL $MMTP,$MMBT ;TOP/BOTTOM BOUNDS OF CODE SPACE .GLOBL $ERR5 ;KERNEL STORAGE EXHAUSTED ERROR .GLOBL $ERR7 ;SYSTEM STORAGE EXAUSTED ERROR .GLOBL $ERR10 ;INVALID BUFFER ADDRESS ERROR .PAGE .CSECT MOS $MMTP: ;TOP BOUND ON MOSMEM CODE SPACE .SBTTL $INIPL - INITIALIZE STORAGE POOLS & DESCRIPTOR TABLE ; INITIALIZE THE KERNEL FREE STORAGE POOL $INIPL: MOV NKBLKS,R0 ;GET NUMBER OF BLOCKS MOV #$BLKPL,R1 ; ADDRESS OF KERNEL POOL MOV #BLKLEN,R2 ;AND SIZE OF EACH BLOCK MOV R1,$FBLKQ ;PUT FIRST BLOCK ON FREE QUEUE BR 2$ ;ENTER LOOP 1$: MOV R1,(R3) ;LINK TO NEXT BLOCK ON CHAIN 2$: MOV R1,R3 ;REMEMBER CURRENT BLOCK POINTER ADD R2,R1 ;ADVANCE POINTER BY BLOCK SIZE $LOOP R0,1$ ;AND INIT ALL BLOCKS CLR (R3) ;GROUND LAST LINK ; FIND LOW ADDRESS OF SYSTEM FREE STORAGE MOV #FSPACE,R0 ;GET ADDRESS OF START OF FREE STORAGE MOV #D.SYMT,R1 ;GET BASE ADDR OF DDT SYMBOL TBL BEQ 4$ ;SKIP IF NO SYMBOL TABLE IN SYSTEM CMP -(R1),-(R1) ;BACK UP TO PREVIOUS SYMBOL 3$: CMP (R1)+,(R1)+ ;ADVANCE TO NAME FIELD OF NEXT SYM CMP (R1)+,(R1) ;EACH RAD50 HALF BOTH EQUAL BNE 3$ ;IF NOT, NOT END OF TABLE TST (R1) ;TEXT OF SYMBOL NULL BNE 3$ ;IF NOT, NOT END OF TABLE MOV R1,R0 ;MAKE END OF SYM TAB START OF FREE MEM TST (R0)+ ;SKIP PAST LAST SYMBOL ENTRY 4$: MOV R0,$BTMEM ;AND INDICATE BOTTOM OF FREE SPACE MOV R0,$LOMEM ; AND STORAGE AREA ; FIND HIGH ADDRESS OF SYSTEM MEMORY $PUSH @#4,@#6 ;SAVE ERROR TRAP VECTORS MOV #MEMTRP,@#4 ;AND TEMP REPLACE W OUR CATCHER MOV #340,@#6 5$: MOV #65432,(R0) ;POKE MEMORY CELL CMP #65432,(R0)+ ;DID IT MAKE IT? BNE BDMEM ;IF NOT, NO MORE READ/WRITE MEMORY TST ENDMEM ;UPPER LIMIT SPECIFIED? BEQ 5$ ;NO, KEEP GOING CMP R0,ENDMEM ;PAST LIMIT? BLO 5$ ;NOPE, ZIP ON BR BDMEM ;ELSE, END OF MEM MEMTRP: CMP (SP)+,(SP)+ ;REMOVE TRAP ADDR & PS BDMEM: $POP @#6,@#4 ;RECOVER TRAP VECTORS SUB #2,R0 BIC #1,R0 ;ROUND DOWN TO EVEN ADDR MOV R0,$TPMEM ;AND REMEMBER TOP ADDRESS SUB $BTMEM,R0 ;CALCULATE AMOUNT OF FREE SPACE MOV R0,$FRMEM ;AND SAVE AWAY ; INIT THE MEMORY DESCRIPTOR TABLE ENTRIES MOV #$MEMDT,R3 ;ADDR OF MEMORY DESCRIPTOR TABLE BR 2$ ;AND ENTER LOOP 1$: TST (R3)+ ;SKIP LENGTH OF EACH BLOCK CLR (R3)+ ;RESET FIRST BLOCK PTR ON LIST 2$: TST (R3) ;REACHED END OF TABLE? BNE 1$ ;IF NOT, INITIALIZE NEXT POOL RTS PC .PAGE .SBTTL $GTBLK - GET KERNEL STORAGE BLOCK ; ; RETURNS WITH: R0 - ADDRESS OF KERNEL STORAGE BLOCK ; $GTBLK: MOV $FBLKQ,R0 ;GET ADDRESS OF FIRST FREE BLOCK BEQ ERR5 ;IF STORAGE EXHAUSTED, ERROR MOV (R0),$FBLKQ ;DELINK BLOCK RTS PC ;RETURN TO CALLER ERR5: BUGHLT ;KERNEL STORAGE EXHAUSTED ERROR HALT $ERR5: NOP .SBTTL $RLBLK - RELEASE KERNEL STORAGE BLOCK ; ; CALLED WITH: R0 - ADDRESS OF KERNEL STORAGE BLOCK ; $RLBLK: MOV $FBLKQ,(R0) ;LINK TO NEXT BLOCK IN LIST MOV R0,$FBLKQ ;AND PUT NEW BLOCK AT HEAD RTS PC ;AND RETURN .PAGE .SBTTL $AVS - ALLOCATE A PACKET BUFFER ; CALLED WITH: R0 - LENGTH OF DESIRED BUFFER ; ; RETURNS WITH: R0 - UNCHANGED ; R2 - ADDRESS OF PACKET BUFFER $AVS: $PUSH R0,R1 JSR PC,GTPL ;GET ADDR OF PACKET BUF POOL DSC 1$: JSR PC,GTBUF ;GET BUFFER AT HEAD OF POOL BNE 2$ ;IF SOME, RETURN JSR PC,DSCHD ; IF NO STORAGE, RUN SCHEDULER BR 1$ ; TRY AGAIN 2$: $POP R1,R0 $RTT ;AND RETURN .SBTTL $ALS - ALLOCATE BUFFER AND RETURN IF NO STORAGE ; ; CALLED WITH: R0 - BYTE COUNT ; ; RETURNS WITH: R2 - ADDRESS OF BUFFER ; IF 0, NO BUFFER AVAILABLE ; $ALS: $PUSH R0,R1 JSR PC,GTPL ; GET R1 =A(BUFFER POOL FOR THIS SIZE) JSR PC,GTBUF ; GET BUFFER ADDRESS INTO R2 $POP R1,R0 $RTT .SBTTL $SCK - STORAGE CHECK ; CALLED WITH: R0 - BYTES REQUESTED ; ; RETURNS WITH: R0 - BYTES REQUESTED IF IT EXISTS ; 0 OTHERWISE $SCK: $PUSH R1 JSR PC,GTPL ; R1 = A(BUFFER POLL FOR THIS SIZE) TST (R1) ; ANY BUFFERS LEFT? BNE 1$ ; YES ==> RETURN CMP -2(R1),$FRMEM ; ENOUGH IN FREE STORAGE? BLOS 1$ ; YES ==> RETURN CLR R0 ; ELSE INDICATE NO STORAGE 1$: $POP R1 $RTT .PAGE .SBTTL GTBUF - GET BUFFER ; CALLED WITH: R1 - POOL DESCRIPTOR LINK ADDRESS ; ; RETURNS WITH: R2 - ADDRESS OF BUFFER ; IF 0, NO BUFFER AVAILABLE GTBUF: MOV (R1),R2 ;GET BLOCK AT HEAD OF POOL BEQ 2$ ;IF NONE, SEE IF FREE SPACE MOV (R2),(R1) ;DELINK BUFFER 1$: TST R2 ;SET CONDITION CODE RTS PC ;AND RETURN 2$: CMP -2(R1),$FRMEM ;SUFFICIENT SPACE LEFT? BHI 1$ ;IF NOT, EXIT WITH R2 = 0 SUB -2(R1),$FRMEM ;SUB SPACE USED MOV $BTMEM,R2 ;GET ADDR OF BUFFER ADD -2(R1),$BTMEM ;ADVANCE BOTTOM OF MEMORY BR 1$ ;AND EXIT .PAGE .SBTTL $FVS - RELEASE A PACKET BUFFER ; CALLED WITH: R0 - LENGTH OF BUFFER ; R2 - ADDRESS OF PACKET BUFFER $FVS: $PUSH R1 CMP R2,$LOMEM ;CHECK IF BUFFER IN POOL AREA BLO ERR10 ;IF NOT, ERROR JSR PC,GTPL ;GET PACKET POOL DESCRIPTOR ADDR MOV (R1),(R2) ;LINK TO NEXT BUFFER IN LIST MOV R2,(R1) ;AND PUT NEW BUFFER AT HEAD $POP R1 $RTT ;AND RETURN ERR10: BUGHLT ;INVALID BUFFER ADDRESS ERROR $ERR10: NOP .PAGE .SBTTL GTPL - GET POOL DESCRIPTOR ADDRESS ; CALLED WITH: R0 - LENGTH OF BUFFER ; ; RETURNS WITH: R1 - POOL DESCRIPTOR LINK ADDRESS GTPL: MOV #$MEMDT,R1 ;GET POOL DESCRIPTOR TABLE ADDR BR 2$ ;AND ENTER LOOP 1$: TST -(R1) ;END OF TABLE MARKER? BEQ ERR7 ;IF SO, ERROR ADD #SDLEN,R1 ;ADVANCE TO NEXT ENTRY 2$: CMP R0,(R1)+ ;BELONG IN THIS POOL? BHI 1$ ;IF NOT, CHECK NEXT RTS PC ERR7: BUGHLT $ERR7: NOP .PAGE .SBTTL MEMSTAT - CALCULATE SOME MEMORY STATS ; RETURNS WITH: R0 - AMOUNT OF SPACE IN USE ; R1 - AMOUNT OF SPACE IDLE ; R2 - AMOUNT OF SPACE FREE $MSTAT: MOV $FRMEM,R2 ;GET AMOUNT OF FREE MEMORY $PUSH R3,R4,R5 CLR R1 MOV #$MEMDT,R3 ;GET MEMORY DESCRIPTOR TBL ADDR 1$: MOV (R3)+,R4 ;GET POOL SIZE BEQ 3$ ;IF ZERO, END OF TBL MARKER MOV (R3)+,R5 ;GET START OF BUFFER LINK LIST BEQ 1$ ;IF ZERO, GOTO NEXT POOL 2$: ADD R4,R1 ;ACCUMULATE AMOUNT OF IDLE SPACE MOV (R5),R5 ;GET NEXT LINK BNE 2$ ;AND LOOP BR 1$ 3$: $POP R5,R4,R3 MOV $BTMEM,R0 ;GET BTM ADDR OF FREE AREA SUB $LOMEM,R0 ;CALCULATE SIZE OF IDLE/BUSY AREA SUB R1,R0 ;SUB IDLE FROM THAT TO GET BUSY SIZE RTI $MMBT: ;END OF CODE SPACE .PAGE .CSECT MOSDAT, STATIC .SBTTL $BLKPL - KERNEL STORAGE BLOCK POOL $FBLKQ: .WORD 0 ;LIST OF FREE KERNEL BLOCKS .EVEN .SBTTL MEMORY ALLOCATION INFO LOMEM: $LOMEM: .WORD 0 ;BOTTOM ADDR OF STORAGE AREA BTMEM: $BTMEM: .WORD 0 ;BOTTOM ADDRESS OF FREE AREA TPMEM: $TPMEM: .WORD 0 ;TOP ADDRESS OF FREE AREA FRMEM: $FRMEM: .WORD 0 ;SIZE OF FREE AREA .END