.TITLE PNS$VI - NON-SWAPPED POOL SUBROUTINES .SBTTL PNS$VI - TITLE PAGE .PSECT VMX$$$,RO,I .IDENT /V01.01/ .ENABL LC ; ; ************************************************************************ ; * ; THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS ONLY. DIGITAL EQUIPMENT * ; COMPUTER USER'S SOCIETY, DIGITAL EQUIPMENT CORPORATION, MONSANTO, AND * ; THE AUTHOR DISCLAIM ALL WARRANTIES ON THE PROGRAM, INCLUDING WITHOUT * ; LIMITATION, ALL IMPLIED WARRANTIES OF MERCHANTABLITY AND FITNESS. * ; * ; FULL PERMISSION AND CONSENT IS HEREBY GIVEN TO DECUS AND TO THE DECUS * ; SPECIAL INTEREST GROUPS TO REPRODUCE, DISTRIBUTE, AND PUBLISH AND * ; PERMIT OTHERS TO REPRODUCE IN WHOLE OR IN PART, IN ANY FORM AND * ; WITHOUT RESTRICTION, THIS PROGRAM AND ANY INFORMATION RELATING TO IT. * ; * ; ************************************************************************ ; ; NON-SWAPPED POOL SUBROUTINES ; ; VERSION: V01.01 ; ; AUTHOR: R.W. STAMERJOHN MAPC 03-NOV-81 ; ; MODIFICATION HISTORY: ; ; V01.01 RWS 03-NOV-81 INITIAL VERSION ; .SBTTL PNS$VI - DECLARATIONS .DSABL GBL .DSABL CRF ; ; MACRO LIBRARY CALLS: ; .MCALL CALLR ;Call subroutine and return .MCALL EXTK$S ;Extend task directive .MCALL GPRT$S ;Get partition parameters .MCALL GTSK$S ;Get task parameters ; ; GLOBAL DECLARATIONS: ; .GLOBL INI$VI ;Create initial pool .GLOBL LCK$VI ;Lock virtual buffer .GLOBL MAP$VI ;Map virtual buffer .GLOBL MRK$VI ;Mark virtual buffer written .GLOBL NEW$VI ;Add more virtual address space .GLOBL RGD$VI ;Process regions descriptor .GLOBL SBF$VI ;Process allocation size .GLOBL SWD$VI ;Process swapping descriptor .GLOBL S16$VI ;Process 16-bit VM_address, size .GLOBL S32$VI ;Process 32-bit VM_address, size .GLOBL ULK$VI ;Unlock virtual buffer .GLOBL VIR$VI ;Map virtual buffer to user .GLOBL XFR$VI ;Transfer buffer (from VM) .GLOBL XFW$VI ;Transfer buffer (to VM) ; ; GLOBAL REFERENCES: ; ; RSX-11M variables. ; .GLOBL $DSW ;Directive status return ; ; VM subroutines. ; .GLOBL ERR$VF ;Declare fatal error .ENABL CRF .SBTTL PNS$VI - DATA DECLARATIONS ; ; The following is the data base used by this version of the VM. This ; data must be kept in the lowest segment of the task which is using ; the pool (cannot be overlayed). ; .PSECT VMXDAT,RW,D,GBL,OVR INCSIZ = 7 ;Allocation increment MAXSIZ: .WORD 0 ;Maximum size of pool CURSIZ: .WORD 0 ;Current size of pool EXTSIZ: .WORD 0 ;Pool extension size POLADR: .WORD 0 ;Starting memory address of pool TSKLMT: .LIMIT ;Task address limits .PSECT VMX$$$,RO,I,LCL ; ; Define error codes: ; ALF$VE = 0 ;Allocation failure BVB$VE = 2 ;Bad VM_buffer BSZ$VE = 4 ;Bad VM_buffer size NSP$VE = 6 ;Not supported PIF$VE = 10 ;Pool initialization failed ; ; Define error message index table. ; ERRCDE: .WORD ALFMSG ;Allocation failure .WORD BVBMSG ;Bad VM_buffer .WORD BSZMSG ;Bad VM_buffer size .WORD NSPMSG ;Not supported .WORD PIFMSG ;Pool initialization failed ; ; Define error messages. ; .NLIST BEX ALFMSG: .ASCIZ /?VMXALF - VM allocation failed/ BVBMSG: .ASCIZ /?VMXBVB - Bad VM buffer/ BSZMSG: .ASCIZ /?VMXBSZ - Bad VM buffer size/ NSPMSG: .ASCIZ /?VMXNSP - VM call not supported in this version/ PIFMSG: .ASCIZ /?VMXPIF - VM pool initialization failed/ .LIST BEX .EVEN .SBTTL ERR$VI * PROCESS ERROR ; ;+ ; This routine process errors declared in processing various requests. ; It gets the error message and calls the the language handler error ; routine. ; ; INPUT: ; ; Call by: JSR PC,ERR$VI ; .WORD error code ; ; OUTPUT: ; ; R0 = Start of ASCIZ message string ; R1 = Error code ; ; REGISTERS: ; ; Uses: R0-R5 Saves: N.A. Stack: 1 words ;- ERR$VI:: ;Ref label MOV @(SP),R1 ;Get error code 1000$: MOV ERRCDE(R1),R0 ;Get address of error message CALLR ERR$VF ;Call error handler .SBTTL INI$VI * CREATE INITIAL POOL SPACE ; ;+ ; This routine creates the initial pool space, based on the parameters ; supplied by the caller on how the space is to be processed. ; ; INPUT: ; ; Call by: JSR PC,INI$VI ; ; R0,R1 = Maximum size of pool ; R2 = Pool extension size ; ; OUTPUT: ; ; Initial pool space allocated. R3 returns minumum pool allocation ; and R4,R5 are set to initial pool allocation size. Enough space ; for header and free cell are guarenteed or fatal error declared. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: none Stack: 16 words ;- INI$VI:: ;Ref label ; ; Process input parameters. Range check and store for later use. ; ; Process maximum pool size. If none, use a default of 32 KW's. ; Otherwise, use whatever limit is given. ; MOV #177777,MAXSIZ ;Preset maximum size to limit TST R0 ;Is over 32K's set as maximum? BNE 1000$ ; If NE - yes, use default TST R1 ;Was any size specified? BEQ 1000$ ; If NE - yes, use default MOV R1,MAXSIZ ;Set maximum pool size ; ; Process extension size. If none, use a default of 1 KW's. If over ; 4 KW's, set a limit to that. ; 1000$: MOV #20000,EXTSIZ ;Preset extended size to 4 KW CMP R2,#20000 ;Is value over the limit? BHIS 2000$ ; If HIS - yes, use maximum default MOV #4000,EXTSIZ ;Preset extend size to 1 KW ADD #77,R2 ;Round up to 32-word boundary BIC #77,R2 ; ... for task extension BEQ 2000$ ; If EQ - use default value MOV R2,EXTSIZ ;Set user specified extension size ; ; Get first available address in task. ; 2000$: MOV #INCSIZ,R3 ;Get minimum buffer allocation MOV TSKLMT+2,R4 ;Get first free address in task ADD R3,R4 ;Round up to allocation boundary BIC R3,R4 ; ... to get correct first free address MOV R4,POLADR ;Set starting physical address of pool ; ; Get information about task size (starting virtual address and task window ; zero size). ; SUB #16.*2,SP ;Get space for dynamic buffer MOV SP,R0 ;Copy buffer address GPRT$S ,R0 ;Get partition parameters SUB $DSW,R4 ;Get true size of task code GTSK$S ,R0 ;Get task parameters MOV G.TSTS(R0),R5 ;Get task window 0 size SUB R4,R5 ;Get size of available space in root ADD #16.*2,SP ;Restore stack space MOV R3,R0 ;Get minumun pool size as twice ASL R0 ; allocation increment size CMP R0,R5 ;Is enough space available? BHIS 3000$ ; If HIS - yes, continue ; ; Try extending task size by specified increment. ; MOV EXTSIZ,R2 ;Get extension size ASH #-6,R2 ; ... in 32W blocks EXTK$S R2 ;Attempt to extend task BCC 2000$ ; If CC - ok, repeat operation CALL ERR$VI ;Declare fatal error .WORD PIF$VE ; Pool initialization failed ; ; Allocation OK, set current end of pool and return. ; 3000$: MOV R5,CURSIZ ;Set current size of pool CLR R4 ; ... as a double word INC R3 ;Set minumum allocation size RETURN ;Return to caller .SBTTL LCK$VI * LOCK VIRTUAL BUFFER ; ;+ ; This routine is the pool-type specific routine used to lock a virtual ; buffer into memory. ; ; INPUT: ; ; Call by: JSR PC,LCK$VI ; ; R0,R1 = Virtual address ; R3 = Size to lock (bytes) ; ; OUTPUT: ; ; For the non-swapped pool, this routine is a no-op. ; ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 0 words ;- LCK$VI:: ;Ref label RETURN ;Return to caller .SBTTL MAP$VI * MAP VM BUFFER ; ;+ ; This routine maps the specified VM buffer and returns the mapped ; starting address. ; ; INPUT: ; ; Call by: JSR PC,MAP$VI ; ; R0,R1 = Virtual address ; R3 = Size to map (bytes) ; ; OUTPUT: ; ; The mapped address is returned in R5. This is done by adding ; in the starting offset of the VM pool area to the VM_address. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 0 words ;- MAP$VI:: ;Ref label MOV R1,R5 ;Copy virtual address ADD POLADR,R5 ;Add in start of actual pool RETURN ;Return to caller .SBTTL MRK$VI * MARK VIRTUAL BUFFER WRITTEN ; ;+ ; This routine is the pool-type specific routine to mark the given ; virtual buffer as written so it will be correctly swapped. ; ; INPUT: ; ; Call by: JSR PC,MRK$VI ; ; R0,R1 = Virtual address ; R3 = Size to mark (bytes) ; ; OUTPUT: ; ; For the non-swapped pool, this routine is a no-op. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 0 words ;- MRK$VI:: ;Ref label RETURN ;Return to caller .SBTTL NEW$VI * ALLOCATE MORE SPACE FOR POOL ; ;+ ; This routine is called when no free space is found for an allocation ; request. It attempts to allocate more space to the VM pool. If this ; fails, an allocation error is declared. ; ; INPUT: ; ; Call by: JSR PC,NEW$VI ; ; R0,R1 = Address of last free cell in pool ; R5 = Logical address of last free cell ; ; MAXSIZ = User specified pool limit ; CURSIZ = Current size of pool ; EXTSIZ = Pool extentsion size ; ; OUTPUT: ; ; A new segment of EXTSIZ created and deallocated as free pool space. ; If the MAXSIZ limit is reached, or the segement creation fails, a ; fatal allocation error (ALF$VE) is declared. R0,R1 are address of ; next cell to be examined. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: none Stack: 1 words ;- NEW$VI:: ;Ref label CMP CURSIZ,MAXSIZ ;Can we allocate new space? BGE 9000$ ; If GE - no, allocation error MOV EXTSIZ,R3 ;Get task extension size MOV R3,R2 ;Copy extension size and convert ASH #-6,R2 ; ... to 32-word blocks EXTK$S R2 ;Attempt to extend the task BCS 9000$ ; If CS - no, allocation error ; ; Deallocate new space to pool as buffer, starting at CURSIZ and with ; size of EXTSIZ. See if new space appends to last cell. If so, add ; space to last cell. Otherwise, link space as new free cell. We know ; only 16-bit addresses are being use, so double precesion arithmetic ; for this version is unnesssary. ; MOV CURSIZ,R4 ;Get current size of pool ADD R3,CURSIZ ;Update current size of pool ADD 6(R5),R1 ;Get end of current free cell CMP R1,R4 ;Does new space append this space? BNE 1000$ ; If NE - no, create new cell ADD R3,6(R5) ;Add new space to last cell BR 1100$ ; and just exit 1000$: MOV R4,2(R5) ;Store link to next cell MOV R4,R1 ;Set new virtual address CALL MAP$VI ; And get logical address CLR (R5)+ ;Set no forward pointer CLR (R5)+ ; ... in the new cell CLR (R5)+ ;Set size of cell MOV R3,(R5)+ ; ... as extension size 1100$: RETURN ;Return to caller 9000$: CALL ERR$VI ;Declare fatal error .WORD ALF$VE ; Allocation failure .SBTTL RGD$VI * PROCESS REGION DESCRIPTOR ; ;+ ; This routine processes the region descriptor when creating the initial ; pool. The region_descriptor is required for PLAS versions and is ignored ; for other versions. The format of the 06-word array is as follows (all ; sizes are in bytes): ; ; |=======================================| ; | Starting APR (no default) | 00 ; |---------------------------------------| ; | | 02 ; |-- Region Size (default pool_size) --| ; | | 04 ; |---------------------------------------| ; | Window Size (default 4 K Words) | 06 ; |---------------------------------------| ; | | 10 ; |-- Region Name (default blank) --| ; | | 12 ; |=======================================| ; ; ; INPUT: ; ; Call by: JSR PC,RGD$VI ; ; R3 = Region descriptor address (or zero) ; ; OUTPUT: ; ; For the non-swapped pool, this routine is a no-op. ; ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R5 Stack: 0 words ;- RGD$VI:: ;Ref label RETURN ;Return to caller .SBTTL SBF$VI * PROCESS ALLOCATION SIZE ; ;+ ; This routine range checks the allocation size for validity. If the size ; is invalid, a fatal bad size error (BSZ$VE) is declared. ; ; INPUT: ; ; Call by: JSR PC,SBF$VI ; ; R3 = Size to allocate/deallocate (bytes) ; ; OUTPUT: ; ; For the non-swapped pool, the size must be 16-bits only and cannot ; be zero. The size is rounded up to the allocation boundary. ; ; R3 = Size rounded up to allocation bounds ; R5 = Allocation increment+1 ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R1 Stack: 0 words ;- SBF$VI:: ;Ref label TST R3 ;Is size zero? BEQ 9000$ ; If EQ - yes, error MOV #INCSIZ,R5 ;Get size increment ADD R5,R3 ;Round allocation size to BIC R5,R3 ; boundary of pool INC R5 ;Set smallest cell size RETURN ;Return to caller 9000$: CALL ERR$VI ;Call fatal error routine .WORD BSZ$VE ; for bad VM_buffer size .SBTTL SWD$VI * PROCESS SWAPPING DESCRIPTOR ; ;+ ; This routine processes the swapping descriptor for initial pool creation. ; The swapping_descriptor is required for disk-based versions and is ignored ; otherwise. The format of the 06-word array is as follows (all sizes are ; in bytes): ; ; |=======================================| ; | Swapping LUN (required) | 00 ; |---------------------------------------| ; | Device Name (default "SY") | 02 ; |---------------------------------------| ; | Device Unit (default zero) | 04 ; |---------------------------------------| ; | Swapping Size (default 512) | 06 ; |---------------------------------------| ; | Swapping Buffer Address (required) | 10 ; |---------------------------------------| ; | Swapping Buffer Size (required) | 12 ; |=======================================| ; ; Note, the swapping buffer is used to map the current in-core ; mapping to the correct virtual address. Each cell is three ; words and maps a unit of the swapping size. The available space ; in the swapping buffer will limit (if necessary) the space ; allocated in the task image or in the region. The buffer must ; in the root of the task. ; ; ; INPUT: ; ; Call by: JSR PC,SWD$VI ; ; R4 = Swapping descriptor address (or zero) ; ; OUTPUT: ; ; For the non-swapped pool, this routine is a no-op. ; ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R5 Stack: 0 words ;- SWD$VI:: ;Ref label RETURN ;Return to caller .SBTTL S16$VI * CHECK ADDRESS, SIZE .SBTTL S32$VI * CHECK ADDRESS, SIZE ; ;+ ; This routine checks a VM_address and size to make sure it falls inside the ; pool. The difference in entries is whether the size is checked to make sure ; it can be entirely mapped by the window. ; ; INPUT: ; ; Call by: JSR PC,S??$VI ; ; R0,R1 = Virtual address ; R3 = Size of VM buffer (bytes) ; ; OUTPUT: ; ; If the buffer does not fall within the pool, a bad buffer error ; (BVB$VE) is declared. For non-swapped pool, both entries are the ; same. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: all Stack: 1 words ;- S16$VI:: ;Ref label S32$VI:: ;Ref label TST R0 ;Is address > 16-bits BNE 9000$ ; If NE - yes, bad address MOV R3,-(SP) ;Copy size of buffer ADD R1,(SP) ;Get end of VM buffer BCS 9000$ ; If CS - bad buffer address CMP (SP)+,CURSIZ ;Is end of buffer within VM space BHI 9000$ ; If HI - no, bad size RETURN ;Return to caller 9000$: CALL ERR$VI ;Declare fatal error .WORD BVB$VE ; Bad VM_buffer .SBTTL ULK$VI * UNLOCK VIRTUAL BUFFER ; ;+ ; This is the pool-type specific routine to unlock a virtual buffer ; and make eligible for swapping. ; ; INPUT: ; ; Call by: JSR PC,ULK$VI ; ; R0,R1 = Virtual address ; R3 = Size to unlock (bytes) ; ; OUTPUT: ; ; For the non-swapped pool, this routine is a no-op. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 0 words ;- ULK$VI:: ;Ref label RETURN ;Return to caller .SBTTL VIR$VI * MAP POOL TO USER BUFFER ; ;+ ; This routine maps the pool buffer to the given user address. ; ; INPUT: ; ; Call by: JSR PC,VIR$VI ; ; R0,R1 = Virtual address ; R3 = Size to map (bytes) ; R4 = User address ; ; OUTPUT: ; ; Dynamic mapping is not possible for pool versions, so a ; fatal error is returned. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 1 words ;- VIR$VI:: ;Ref label CALL ERR$VI ;Declare fatal error .WORD NSP$VE ; Not supported .SBTTL XFR$VI * TRANSFER BUFFER (FROM VM) .SBTTL XFW$VI * TRANSFER BUFFER (TO VM) ; ;+ ; These routines transfer buffers from/to the VM space and a user buffer. ; They use a transfer vector for speed considerations. ; ; INPUT: ; ; Call by: JSR PC,XF?$VI ; ; R3 = Size to transfer (bytes) ; R4 = User buffer address ; R5 = VM buffer address ; ; OUTPUT: ; ; Buffer is transfered in direction wanted. Saves user buffer (R4) and ; size values (R3). ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 2 words ;- ; ; Entry for transfer from user buffer to VM_address. ; XFW$VI:: ;Ref. label MOV R4,-(SP) ;Save user address MOV R5,R4 ;Set source address MOV (SP),R5 ;Set destination address BR XFC$VI ; And continue ; ; Entry for transfer from VM_address to user buffer. ; XFR$VI:: ;Ref. label MOV R4,-(SP) ;Save user buffer ; ; Common code, transfer from R3 to R5. ; XFC$VI: ;Ref. label MOV R3,-(SP) ;Save transfer size ; ; Test for odd transfer addresses. ; MOV #1,-(SP) ;Push low bit mask BIT (SP),R5 ;Is source address odd? BEQ 1000$ ; If EQ - no, skip MOVB (R5)+,(R4)+ ;Move the first byte DEC R3 ; and count a byte moved 1000$: BIT (SP),R4 ;Is destination address odd? BNE 3000$ ; If NE - yes, use byte moves ; ; Enter word move transfer vector. ; 2000$: SUB #32.*2.,R3 ;Subtract one transfer from size BCC 2200$ ; If CC - use whole vector BIC R3,(SP) ;Remaining count odd? BNE 2100$ ; If NE - no, skip DEC R3 ;Adjust negative count 2100$: SUB R3,PC ;Index into transfer vector 2200$: .REPT 32. MOV (R5)+,(R4)+ ;Transfer a word .ENDR BCC 2000$ ;If CC - more to go BR 4000$ ; Otherwise, just exit ; ; Enter byte move transfer vector. ; 3000$: ASL R3 ;Double the count 3100$: SUB #32.*2.,R3 ;Subtract one transfer from size BCC 3200$ ; If CC - use whole vector SUB R3,PC ;Index into transfer vector 3200$: .REPT 32. MOVB (R5)+,(R4)+ ;Transfer a byte .ENDR BCC 3100$ ;If CC - more to go ; ; Finish up. ; 4000$: TST (SP)+ ;Clean off constant BNE 4100$ ; If NE - done MOVB (R5)+,(R4)+ ;Move last byte 4100$: MOV (SP)+,R3 ;Restore buffer size MOV (SP)+,R4 ;Restore user buffer RETURN ;Return to caller .END