.include '$common.mac' .include '$config.mac' .include '$kernel.mac' .title getwcb - Get window control blocks for a program. ; ; This routine is called to return all the WCBs/DDBs for a program from both ; the IOB and PFB. It uses the new features of RSTS V9.0 to map physical ; memory in order to save doing a lot of .PEEKs, and also because channels ; 0 and 1 in the PFB point to addresses in XBUF which cannot be reached using ; .PEEKs. ; ; Calling sequence: ; CALL GETWCB BY REF (JDB, WCBBLK) ; where: ; JDB is the job's Job Data Block address as determined by SYSTAT ; WCBBLK is the address of a 32 word array to be written to ; by GETWCB with the addresses of the user's IOB and PFB info ; (after following links into XBUF to find the associated WCB's ; for channels 0 and 1 in the PFB). ; ; If the job has an open command file or log file, the channel pointers in the ; PFB point to a buffer in XBUF with the following format: ; ; PF.BUF: 512. byte disk block buffer ; PF.VBL: Current virtual block number (LSB) ; PF.BYT: Points to the next character in PF.BUF ; PF.FLG: Various status flags of which only bit 2 (PF.ACT) may ; be relavent. If set then the log file or command file ; is 'active'. Do not know why this bit would be cleared ; even though the PFB points to the block. I would expect ; the block to be deallocated if the file was closed. ; PF.WCB: Pointer back to the WCB for the file. This is the only ; word we are really interested in. ; PF.BC: Saved XRBC when having to do disk block I/O to get/store ; some characters. ; PF.BLK: Saved XRBLK for same reason. ; PF.ERS: Error sequence counter. (?) ; PF.ERR: Status code from last I/O transfer. If zero no errors. ; PF.VBH: Virtual block number (MSB) ; PF.BLM: Saved XRBLKM. See PF.BC. ; .asect . = 0 pf.buf: .blkb 512. pf.bvl: .blkw 1 pf.byt: .blkw 1 pf.flg: .blkw 1 pf.cr = 1 ;Implied carriage return required pf.lf = 2 ;Implied line feed required pf.act = 4 ;Log file or command file is active pf.inv = 10 ;No valid data in buffer (buffer empty) pf.c1p = 20 ;C1 control is pending ; 40 ;Reserved pf.tim = 100 ;Timestamping is enable for this log file pf.bor = 200 ;Next character read is beginning of record pf.tsp = 200 ;Time stamp is being written to log file. ; ; NOTE: pf.bor and pf.tsp have same value. pf.bor is only for command files ; and pf.tsp is only for log files. ; NOTE: Bits 8-15 (400-100000) are currently unused. ; pf.wcb: .blkw 1 pf.bc: .blkw 1 pf.blk: .blkw 1 pf.ers: .blkb 1 pf.err: .blkb 1 pf.vbh: .blkb 1 pf.blm: .blkb 1 ; ; The above information is taken from the RSTS/E V9 Internals and Data ; Structures manual (order number AA-CL35B-TC) (C) 1984 by Digital Equipment ; Corporation. ; .psect data,d,rw windid: .word 0 ;No window ID yet wndbas: .word 0 ;Window virtual base address lstmap: .word 0 ;MMU address of last map lstlen: .word 0 ;Length of last mapping in MMU's curmap: .word 0 ;MMU address of this map curlen: .word 0 ;Length of current mapping in MMU's iobmsk: .word ^B0000000000000000 ;No XBUF references needed pfbmsk: .word ^B0000000000000011 ;Need XBUF references for channels 0-1 apr5: .word 0 ;Kernal APR5 value .psect getwcb,i,ro getwcb:: cmp #2,(r5)+ ;Two arguments? bne 100$ ;No dont do anything mov r0,-(sp) mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov @(r5)+,r0 ;Get address of JDB mov (r5)+,r4 ;Get address of 32 word block descriptor mov (r4)+,r2 ;Get length of block (s.b. 32.*2) mov (r4)+,r1 ;Get address of 32 word block mov r5,-(sp) ;Now save argument pointer in case BP2 needs it tst windid ;Do we have a window yet? bne 10$ ;Yes, dont create a new one call crewnd ;Create a 4K window for our use 10$: mov r0,r3 ;Address to map mov #1,r4 ;Length to map call mapwnd ;Map to it mov jdjdb2(r4),-(sp) ;Pointer to second job data block mov jdiob(r4),r3 ;Pointer to IOB mov #1,r4 ;Length to map call mapwnd ;Map to the IOB mov iobmsk,r5 ;XBUF map flags call copwcb ;Copy the WCB's bcs 50$ ;No room left, return mov (sp)+,r3 ;Point to second job data block mov #/64.,r4 ;Maximum size we need for accessing JDB2 asl r4 ;Double for safety factor (JDB2 block may not ; start at beginning of area we map to, so ; accessing j2pfb may overflow dynamic buffer. call mapwnd ;Map to it mov j2pfb(r4),r3 ;Get address of PFB beq 40$ ;No PFB (probably a detached job) mov #1,r4 ;Length of PFB call mapwnd ;Map to it. mov pfbmsk,r5 ;XBUF map flags call copwcb ;Copy the WCB's 40$: tst r2 ;Any more entries in passed table? beq 50$ ;No 45$: clr (r1)+ ;Clear rest of table sob r2,45$ 50$: mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 100$: return ; ; Create an address window for use, but do not map it. ; We will create a 4KW window for use, but will probably not use ; more than 260. words at any one time. ; ; Inputs: ; None ; Outputs: ; windid = Window Id ; wndbas = Window base address (should agree with base APR selected here) crewnd: mov r0,-(sp) ;Save a register for use call clrfqb ;Clean out the FIRQB mov #firqb+fqfil,r0 ;Point to where to start movb #crafq,(r0)+ ;Tell .PLAS to create a window cmpb (r0)+,(r0)+ ;Skip unused bytes movb #7,(r0)+ ;Start with APR 7 tst (r0)+ ;Not used mov #4096./32.,(r0)+ ;Want 4KW partition cmp (r0)+,(r0)+ ;Not used (not mapping now) tst (r0)+ ; "" clr (r0)+ ;No write access or mapping now .plas ;Create the window please tst @#firqb ;Any errors? beq 10$ ;No mov @#firqb,r0 ;Get error code mov #-1,r1 ;Show where we are bpt ;;;Sorry 10$: movb @#firqb+fqppn,windid ;Set the window Id mov @#firqb+fqnam1,wndbas ;Set the base virtual address to use tst @#firqb+fqmode ;Window created OK? bmi 20$ ;Yes (should always succeed if no error @#FIRQB) mov @#firqb+fqmode,r0 ;Get window status mov #-2,r1 ;Show where we are bpt ;;;Sorry 20$: mov (sp)+,r0 ;Restore register return ;Done ; ; Map the address window to the requested area. ; ; Inputs: ; r3 = Base address in physical memory (low core monitor addresses) ; r4 = Length to map in 32 word units ; Outputs: ; Mapped to requested area ; r4 = Starting virtual address of requested area in mapped area ; mapwnd: mov r0,-(sp) ;Need a work area clr -(sp) ;Assume data wanted in not in FIP cmp #120000,r3 ;Address in FIP memory? bhi 20$ ;No, ok as is sub #120000,r3 ;Get bias into FIP memory tst apr5 ;Get start of FIP memory bne 10$ ;Have start already mov #172372,@#xrb ;Address of kernal APR 5 data PAR .peek ;Get start of FIP memory in MMUs mov @#xrb,apr5 ;Save it for later 10$: mov apr5,@sp ;Set start of FIP 20$: mov r3,r0 ;Save requested address bic #^C<63.>,r0 ;Save offset to into buffer ash #-6,r3 ;Convert to MMU address bic #176000,r3 ;Drop overflow iff addr >= 100000(8) add (sp)+,r3 ;Add start of FIP if needed call domap ;Call common code add r0,r4 ;Add in offset (S.B. 0 or 40(8)) mov (sp)+,r0 ;Restore used register return ;Simple ; ; Remap to the last mapped window. ; This routine is called to remap from the current window to the last window ; during copy WCB operations, when it becomes necessary to unmap from the IOB ; or PFB long enough to map into XBUF to find the WCB stored in the PFB ; work area and then need to remap back to the IOB or PFB to continue ; processing. ; ; Inputs: ; curmap = Memory address of current window in MMU's ; curlen = Length of current mapping ; lstmap = Memory address of last window in MMU's ; lstlen = Length of last mapping ; Outputs: ; Mapped to (lstmap) again. ; lstmap and curmap values swapped. ; remap: cmp lstmap,curmap ;Same address? bne 10$ ;No cmp lstlen,curlen ;Same length also? beq 100$ ;Yes, no need to remap 10$: mov r3,-(sp) ;Save registers for now mov r4,-(sp) mov lstmap,r3 ;Get the address wanted mov lstlen,r4 ;Get the length wanted call domap ;Do it please mov (sp)+,r4 ;Restore registers mov (sp)+,r3 100$: return ;Simple ; ; Map the address window to the requested area. ; This code does the actual mapping. Since any buffers in XBUF are aligned ; on 32 word boundaries, no offset computations need to be done as may ; need to be done for buffers in monitor low core which are aligned on 32 ; byte boundaries (except for JDB2's which are just byte aligned). ; ; Inputs: ; r3 = Address of requested area in MMU's ; r4 = Length to map in MMU's ; Outputs: ; Mapped to requested area ; r4 = Starting virtual address of mapped area ; domap: cmp r3,curmap ;Already mapped here? bne 5$ ;No cmp r4,curlen ;Same length? beq 100$ ;Yes, no need to map again 5$: mov r0,-(sp) ;Need a work register call clrfqb mov #firqb+fqfil,r0 ;Where to start stuffing movb #mapfq,(r0)+ ;Tell .PLAS we want to map now tstb (r0)+ ;Not used movb windid,(r0)+ ;Window ID as returned by CREWND tstb (r0)+ ;Not used cmp (r0)+,(r0)+ ; "" mov #-4,(r0)+ ;Want to map physical memory mov r3,(r0)+ ;Base address to map in MMU's mov r4,(r0)+ ;Length to map in MMU's clr (r0)+ ;Map read only please .plas ;Do mapping tst @#firqb ;Any errors? beq 10$ ;No mov @#firqb,r0 ;Get error code mov #-3,r1 ;Say where we are bpt ;;;Sorry 10$: mov curmap,lstmap ;Save old mapping in case remap wanted mov curlen,lstlen ;Save old mapping length in case remap wanted mov r3,curmap ;Say where we just mapped to mov r4,curlen ;Say how much we just mapped mov (sp)+,r0 ;Restore work register 100$: mov wndbas,r4 ;Set the base address return ;Bye ; ; Copy the WCB pointers to the user buffer. ; ; Inputs: ; r1 > User buffer ; r2 = Length of buffer in words ; r4 > Start of IOB or PFB ; r5 = Bit mask saying whether current channel needs to be mapped into ; XBUF to find a WCB. Currently only first two channels of PFB ; are mapped through XBUF. ; ; Outputs: ; WCB's copied into buffer ; 'C' set if buffer prematurely full ; 'C' clear if buffer not prematurely full ; copwcb: mov r0,-(sp) ;Need a work buffer mov r3,-(sp) ;Need this if accessing XBUF mov #1,-(sp) ;Bitmask pointer for each channel mov #16.,r0 ;Number of pointers to copy 10$: tst @r4 ;Anything to copy? beq 15$ ;No, copy as is bit @sp,r5 ;Need XBUF for this channel? bne 20$ ;Yes 15$: mov (r4)+,(r1)+ ;Copy pointer br 100$ ;Continue ; ; Pointer points into XBUF, lets find the buffer and get the WCB from it. ; 20$: mov r4,-(sp) ;Save pointer mov @r4,r4 ;Get contorted pointer mov r4,r3 ;Copy pointer to odd register for ASHC ashc #-7,r3 ;Convert to MMU address mov #/64.,r4 ;Length we need to map call domap ;Map it please mov pf.wcb(r4),r4 ;Get the WCB mov r4,(r1)+ ;Store it in user buffer call remap ;Remap to IOB/PFB mov (sp)+,r4 ;Restore pointer to IOB/PFB tst (r4)+ ;Skip this entry (just processed it) 100$: dec r2 ;Count word as used beq 110$ ;No more words left asl @sp sob r0,10$ clc ;Have not filled up array br 120$ ;Clean up ; ; Ran out of array space. Set carry and get out. ; 110$: sec ;Array filled up 120$: mov (sp)+,r3 ;Throw away pointer w/o affecting 'C' flag mov (sp)+,r3 ;Restore registers mov (sp)+,r0 return ;Bye ; ; Clear out the FIRQB prior to .PLAS calls ; clrfqb: mov r0,-(sp) ;Save some registers mov r1,-(sp) mov #firqb,r0 ;Start of FIRQB mov #fqbsiz/2,r1 ;Length of FIRQB in words 10$: clr (r0)+ sob r1,10$ mov (sp)+,r1 ;Restore registers mov (sp)+,r0 return ;Done .end