.TITLE RNS$VI - NON-SWAPPED REGION SUBROUTINES .SBTTL RNS$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 REGION SUBROUTINES ; ; VERSION: V01.01 ; ; AUTHOR: R.W. STAMERJOHN MAPC 03-NOV-81 ; ; MODIFICATION HISTORY: ; ; V01.01 RWS 03-NOV-81 INITIAL VERSION ; .SBTTL RNS$VI - DECLARATIONS .DSABL GBL .DSABL CRF ; ; MACRO LIBRARY CALLS: ; .MCALL CALLR ;Call subroutine and return .MCALL CRRG$S ;Create region .MCALL CRAW$S ;Create address window .MCALL MAP$S ;Map address to region .MCALL RDBBK$ ;Define region descriptor .MCALL WDBBK$ ;Define window descriptor ; ; 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: ; ; VM subroutines. ; .GLOBL ERR$VF ;Declare fatal error .ENABL CRF .SBTTL RNS$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 = 77 ;Allocation increment MAXSIZ: .WORD 0,0 ;Maximum size of pool REGION: RDBBK$ ;Define region descriptor WINDOW: WDBBK$ ;Define window descriptor .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 BRD$VE = 12 ;Bad region descriptor CRF$VE = 14 ;Create region failed CWF$VE = 16 ;Create window failed MWF$VE = 20 ;Mapping window failed BVA$VE = 22 ;Bad virtual address ; ; 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 .WORD BRDMSG ;Bad region descriptor .WORD CRFMSG ;Create region failed .WORD CWFMSG ;Create window failed .WORD MWFMSG ;Mapping window failed .WORD BVAMSG ;Bad virtual address ; ; 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/ BRDMSG: .ASCIZ /?VMXBRD - Bad region descriptor/ CRFMSG: .ASCIZ /?VMXCRF - Create region failed/ CWFMSG: .ASCIZ /?VMXVWF - Create window failed/ MWFMSG: .ASCIZ /?VMXMWF - Mapping window failed/ BVAMSG: .ASCIZ /?VMXBVA - Bad virtual address/ .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 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 MOV R0,MAXSIZ+0 ;Store size of region as pool size MOV R1,MAXSIZ+2 ; ... in double precsision MOV #INCSIZ+1,R3 ;Set minumum allocation size MOV R0,R4 ;Return initial pool size MOV R1,R5 ; ... in double precision RETURN .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 region, 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 R3,-(SP) ;Save size to map MOV R0,-(SP) ;Save virtual address MOV R1,-(SP) ; ... in double precision ; ; See if requested buffer is mapped by current window? ; MOV WINDOW+W.NOFF,R5 ;Get start of current window ASHC #-6,R0 ;Get start of buffer in 32-word blocks CMP R1,R5 ;Is start of buffer mapped? BLO 1000$ ; If LO - no, map buffer ADD #INCSIZ,R3 ;Round size to next 32-word block ASH #-6,R3 ;Get size in 32-word blocks ADD R1,R3 ;Get end of buffer in 32-word blocks ADD WINDOW+W.NLEN,R5 ;Get end of current window CMP R3,R5 ;Is end of buffer mapped? BLO 2000$ ; If LO - yes, continue ; ; Map wanted buffer to current window. ; 1000$: MOV R1,WINDOW+W.NOFF ;Set new start of buffer CLR WINDOW+W.NLEN ;Set to map as much as possible MAP$S #WINDOW ;Map window to buffer BCS 9000$ ; If CS - mapping error ; ; Get offset in window to desired buffer. ; 2000$: MOV WINDOW+W.NOFF,R1 ;Get current offset into window ASH #6,R1 ; as low part of 32-bit address MOV (SP),R5 ;Get virtual address we want SUB R1,R5 ;Get offset into region ADD WINDOW+W.NBAS,R5 ;Get virtual address in window MOV (SP)+,R1 ;Restore virtual address MOV (SP)+,R0 ; ... in double precsion MOV (SP)+,R3 ;Restore buffer size RETURN ;Return to caller 9000$: CALL ERR$VI ;Declare fatal error .WORD MWF$VE ; Mapping failure .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 region, 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 ; ; OUTPUT: ; ; For the non-swapped region, pool extension is not possible and ; this routine declares a pool allocation error. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: none Stack: 1 words ;- NEW$VI:: ;Ref label 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 ; ; R0,R1 = Maximum size of pool ; R3 = Region descriptor address (or zero) ; ; OUTPUT: ; ; The specified region is created and the start of it is mapped with ; the address window. If a permanent region is requested, the region ; will not be deleted on last detach, otherwise, this is the default. ; The actual size of the pool (region size) is returned in R0,R1. ; ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R5 Stack: 0 words ;- RGD$VI:: ;Ref label TST R3 ;Was a region descriptor specified? BEQ 9000$ ; If EQ - no, fatal error ; ; Get size of region to create. Use larger of maximum pool size or size of ; of region, up to limit of RSX-11M regions sizes (65536*32 words). ; CMP R0,2(R3) ;Is maximum size larger than region? BLO 1000$ ; If LO - no, use region size BHI 1100$ ; If HI - yes, use pool size CMP R1,4(R3) ;Is maximum size larger than region BHIS 1100$ ; If HIS - yes, use pool size 1000$: MOV 2(R3),R0 ;Set new maximum pool size MOV 4(R3),R1 ; ... as a double precision number 1100$: ADD #INCSIZ,R1 ;Round size up to 32W block ADC R0 ; ... in double precsion ASHC #-6,R0 ;Get size in 32W blocks TST R0 ; Does the size exceed the maximum BEQ 1200$ ;If EQ - no, continue CLR R0 ;Set size to maximum region MOV #177777,R1 ; ... in 32 word blocks 1200$: MOV R1,REGION+R.GSIZ ;Store size of region to create ASHC #6,R0 ;And set actual size of region ; ; Store region name and set initial status bits. ; MOV 10(R3),REGION+R.GNAM+0 ;Store first part of name MOV 12(R3),REGION+R.GNAM+2 ;Store second part of name MOV #RS.MDL!RS.ATT!RS.WRT!RS.RED,REGION+R.GSTS ; ; Create the region. ; CRRG$S #REGION ;Create the region BCS 9100$ ; If CS - region creation failed ; ; Setup window block to map the first part of the region. ; MOVB (R3),WINDOW+W.NAPR ;Store the APR number MOV R0,-(SP) ;Free R0 as a working register MOV 6(R3),R0 ;Get size of address window BNE 3000$ ; If NE - size specified MOV #4096.,R0 ;Set size to default (4KW's) 3000$: ASH #-6,R0 ;Get size in 32W blocks MOV R0,WINDOW+W.NSIZ ;Store size of window MOV (SP)+,R0 ;Restore R0 value MOV REGION,WINDOW+W.NRID ;Store region ID CLR WINDOW+W.NOFF ;Clear starting address to map CLR WINDOW+W.NLEN ;Clear size to map MOV #WS.MAP!WS.WRT!WS.64B,WINDOW+W.NSTS ; ; Map window into first part of region. ; CRAW$S #WINDOW ;Create address window and map BCS 9200$ ; If CS - mapping failed RETURN ;Return to caller 9000$: CALL ERR$VI ;Call fatal error routine .WORD BRD$VE ; for bad region descriptor 9100$: CALL ERR$VI ;Call fatal error routine .WORD CRF$VE ; for create region failed 9200$: CALL ERR$VI ;Call fatal error routine .WORD CWF$VE ; for create window failed .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 size parameter .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 region, 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 the two entries is whether the size 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 with the pool, a bad VM_buffer error ; (BVB_VE) error is declared. ; ; REGISTERS: ; ; Uses: R0-R5 Saves: all Stack: 2 words ;- .ENABL LSB S16$VI:: ;Ref label MOV R3,-(SP) ;Save size value ADD #INCSIZ,R3 ;Round size to next 32-word BIC #INCSIZ,R3 ; ... block boundary ASH #-6,R3 ;Get size in 32 word blocks CMP R3,WINDOW+W.NSIZ ;Is size within window? BHIS 9000$ ; If HIS - no, error MOV (SP)+,R3 ;Restore size S32$VI:: ;Ref label MOV R1,-(SP) ;Save low part of address ADD R3,(SP) ;Get end of buffer MOV R0,-(SP) ;Save high part of address ADC (SP) ;Get end of buffer BCS 9000$ ; If CS - bad buffer CMP (SP)+,MAXSIZ+0 ;Is address within pool BHI 9000$ ; If HI - no, declare error BLO 1000$ ; If LO - no, exit CMP (SP),MAXSIZ+2 ;Is address within pool BHI 9000$ ; If HI - no, declare error 1000$: TST (SP)+ ;Clear stack RETURN ;Return to caller 9000$: CALL ERR$VI ;Declare fatal error .WORD BVB$VE ; Bad VM_buffer .DSABL LSB .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 region, 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: ; ; ; REGISTERS: ; ; Uses: R0-R5 Saves: R0-R4 Stack: 1 words ;- VIR$VI:: ;Ref label MOV R0,-(SP) ;Save virtual address MOV R1,-(SP) ; ... in double precision ; ; Is user buffer correct for our window? ; CMP R4,WINDOW+W.NBAS ;Is this the correct base address? BNE 9100$ ; If NE - no, declare fatal error BIT #INCSIZ,R1 ;Is address on correct boundary? BNE 9100$ ; If NE - no, declare fatal error ; ; See if requested buffer is mapped by current window? ; ASHC #-6,R0 ;Get start of buffer in 32-word blocks CMP R1,WINDOW+W.NOFF ;Is desired buffer already mapped? BEQ 2000$ ; If EQ - yes, just exit ; ; Map wanted buffer to current window. ; 1000$: MOV R1,WINDOW+W.NOFF ;Set new start of buffer CLR WINDOW+W.NLEN ;Set to map as much as possible MAP$S #WINDOW ;Map window to buffer BCS 9000$ ; If CS - mapping error 2000$: MOV (SP)+,R1 ;Restore virtual address MOV (SP)+,R0 ; ... in double precsion RETURN ;Return to caller 9000$: CALL ERR$VI ;Declare fatal error .WORD MWF$VE ; Mapping window failure 9100$: CALL ERR$VI ;Declate fatal error .WORD BVA$VE ; Bad virtual address .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