.title Ovctr .ident /X13B/ ;+ ; **-Ovctr-Overlay control routines for unmapping and mapping segments ; ; Version X13B ; ; Wayne E. Baisley April 14, 1982 ; ; This module contains two routines: ; ; 1) $Markr - Find and unmap segments which are in the way ; ; Inputs: ; ; R2=Overlay segment descriptor address for segment which is to be loaded ; ; Outputs: ; ; None - All registers are preserved. ; ; 2) $Rdseg - Load (if necessary) and map a specified segment ; ; Inputs: ; ; R2=Optional Overlay segment descriptor address for segment which is to be loaded ; R3=Optional event flag number for the Load Overlay QIO (if required) ; R4=Optional I/O Status Block address for the Load Overlay QIO (if required) ; R5=AST routine address for the Load Overlay QIO (if required) ; ; If both R3 and R4 are zero, the default Event Flag and IOSB from the ; overlay run-time system work area are used. ; ; Outputs: ; ; None - All registers are preserved. ; .page ; ; The Segment Descriptors, which are created by the Task Builder in the ; $$SGD0 psect, have the following format : ; ; +--------+----------------------+ ; 0 | Status | Relative Disk Address| s.stat ; +--------+----------------------+ ; 2 | Load Address | s.addr ; +-------------------------------+ ; 4 | Length in Bytes | s.size ; +-------------------------------+ ; 6 | Link Up (away from root) | s.lkup ; +-------------------------------+ ; 10 | Link Down (toward root) | s.lkdn ; +-------------------------------+ ; 12 | Link Next (to neighbor) | s.lknt ; +-------------------------------+ ; 14 | Segment Name | s.name * ; +--- in ---+ ; 16 | Radix-50 | ; +-------------------------------+ ; 20 | Window Descriptor Address | s.pwdb * ; +-------------------------------+ ; ; * - The Segment Name is appended only if the manual load routine ; ($Load) is used or if memory-resident overlays are included, ; in which case the Window Descriptor Address is also appended. ; ; The status nibble is composed of the following flag bits : ; ; 100000 = Always set to 1 ; 40000 = (ss.nal) Segment has no disk allocation ; 20000 = (ss.dsk) Segment has been loaded from disk ; 10000 = (ss.nld) Segment is not loaded ; .page ; ; The Window Descriptors, which are created by the Task Builder in the ; $$WNDS psect, have the following format : ; ; +---------------+---------------+ ; 0, 1 | Base APR | Window ID | w.nid, w.napr ; +---------------+---------------+ ; 2 | Virtual Base Address | w.nbas ; +-------------------------------+ ; 4 | Window Size in 64-byte blocks | w.nsiz ; +-------------------------------+ ; 6 | Region ID | w.nrid ; +-------------------------------+ ; 10 | Offset in Partition | w.noff ; +-------------------------------+ ; 12 | Length to Map | w.nlen ; +-------------------------------+ ; 14 | Status Word | w.nsts ; +-------------------------------+ ; 16 | Send/Receive Buffer Addr = 0 | w.nsrb ; +-------------------------------+ ; 20 | Flags Word | w.nflg * ; +-------------------------------+ ; 22 | Region Descriptor Address | w.nrda * ; +-------------------------------+ ; ; The first eight words of the Window Descriptor structure constitute ; a standard RSX-11M/M+ Window Descriptor Block, which is used in the ; window mapping directives for memory-resident overlays. If an over- ; lay is part of the task, the Region ID is zero, and the Region Des- ; criptor Address is zero if one has not (yet?) been allocated. For a ; memory-resident overlay in a shared region, there will be a Region ; Descriptor and the Region ID is copied from it whenever the region ; is attached. ; ; * - The Flags Word and Region Descriptor Address are always included ; in this structure by the Task Builder. The flag WF.MAP (bit 15) is ; set whenever this window (and consequently its region) is mapped. ; .page ; ; The Region Descriptors, which are created by the Task Builder in the ; $$RGDS psect, have the following format : ; ; +-------------------------------+ ; 0 | Region ID | r.gid ; +-------------------------------+ ; 2 | Region Size in 64-byte blocks | r.gsiz ; +-------------------------------+ ; 4 | Region Name | r.gnam ; +--- in ---+ ; 6 | Radix-50 | ; +-------------------------------+ ; 10 | Partition Name | r.gpar ; +--- in ---+ ; 12 | Radix-50 | ; +-------------------------------+ ; 14 | Region Status | r.gsts ; +-------------------------------+ ; 16 | Protection Codes = 0 | r.gpro ; +-------------------------------+ ; 20 | Flags Word | r.gflg * ; +-------------------------------+ ; ; * - The Flags Word is always included in this structure by the ; Task Builder. The flag RF.MAP (bit 15) is set whenever this ; region is mapped. ;- .mcall alodf$, filio$, orddf$, owddf$ .mcall atrg$s, craw$s, dir$, elaw$s, wtse$s alodf$ ;define the segment descriptor symbols filio$ ;define the QIO symbols orddf$ ;define the autoload rdb symbols owddf$ ;define the autoload wdb symbols deflag = 31. ;default Event Flag for overlay QIO's qio = 1.+<12.*400> ;QIO directive code .list meb .page .psect $$mrks ro,ovr .enabl lsb $markr:: jsr r5,$savrg ;save the non-volatile registers (3-5) mov @#n.ovpt,r5 ;fetch the overlay work area address cmp n.szsg(r5),#s.lgth ;memory resident overlays to deal with ? blo 20$ ;if lo no (no wdbs were allocated) mov s.pwdb(r2),r4 ;otherwise, get the window descriptor 20$: mov r2,-(sp) ;save R2, the segment descriptor address ; ; Trace back all mapped segments for this window ; 40$: bit #ss.nld,(r2) ;is this segment loaded and mapped ? bne 100$ ;if ne no, look at our neighbors 60$: mov s.lkdn(r2),r2 ;move one level deeper (towards the root) bne 40$ ;if ne we have found another level 80$: mov (sp)+,r2 ;restore the segment descriptor address return ; ; Check all segments on a given level ; 100$: tst s.lkdn(r2) ;is this the root descriptor ? beq 80$ ;if eq yes, we're all done mov r2,-(sp) ;otherwise, save the current address mov r2,-(sp) ;make another copy to play with, also 120$: mov s.lknt(r2),r2 ;pick up our neighbor segment's address cmp r2,(sp) ;have we looked at everyone on this level ? beq 200$ ;if eq yes .page ; ; Unmap a conflicting segment and all its subordinates ; 140$: bit #ss.nld,(r2) ;is this segment loaded and mapped ? bne 120$ ;if ne no, look at another neighbor bis #ss.nld,(r2) ;otherwise, unmap it. Simple, no ? cmp n.szsg(r5),#s.lgth ;memory resident overlays to deal with ? blo 160$ ;if lo no mov s.pwdb(r2),r3 ;otherwise, pick up this segment's wdb cmp r3,r4 ;is this our segment's window ? beq 160$ ;if eq yes, don't eliminate the window bit #wf.map,w.nflg(r3) ;is this segment's window mapped ? beq 160$ ;if eq no, skip it elaw$s r3 ;otherwise, make it go away bic #wf.map,w.nflg(r3) ;mark it as unmapped, too br 180$ ;proceed 160$: bic #ss.dsk,(r2) ;mark this segment as not loaded from disk 180$: mov s.lkup(r2),(sp) ;having found a mapped segment, look for ;any higher segments on this branch beq 200$ ;if eq we've gone as far as we can mov (sp),r2 ;otherwise, unmap them as well ... br 140$ ; 200$: tst (sp)+ ;clean up the stack mov (sp)+,r2 ;restore the original descriptor address br 60$ ;continue looking lower .dsabl lsb .page .psect $$rdsg ro,ovr .enabl lsb ; ; Load a requested segment ; $rdseg: bic #ss.nld,(r2) ;start by assuming a successful mapping jsr r5,$savrg ;save the non-volatile registers (3-5) mov @#n.ovpt,r3 ;fetch the overlay work area address cmp n.szsg(r3),#s.lgth ;memory resident overlays to deal with ? blo 80$ ;if lo no (no wdbs were allocated) mov s.pwdb(r2),r3 ;otherwise, pick up the segment's wdb beq 80$ ;if eq this segment is disk-resident ; ; Attach to the appropriate region, if necessary ; bit #wf.map,w.nflg(r3) ;otherwise is this window already mapped ? bne 80$ ;if ne yes, we must already be attached mov w.nrda(r3),r4 ;otherwise, get the region descriptor addr beq 40$ ;if eq there isn't one bit #rf.map,r.gflg(r4) ;if there is, are we already attached ? bne 20$ ;if ne yes atrg$s r4 ;otherwise, attach it bcs 160$ ;if cs we couldn't bis #rf.map,r.gflg(r4) ;having done so, mark the region as mapped ; ; Create and map the address window, if necessary ; 20$: mov r.gid(r4),w.nrid(r3) ;copy the region id to the wdb 40$: craw$s r3 ;create and map the address window bcc 60$ ;if cc we did it bic #ws.wrt,w.nsts(r3) ;otherwise, try it without write access craw$s r3 ; bcs 160$ ;if cs we got big trouble 60$: bis #wf.map,w.nflg(r3) ;tell ourself we have the window mapped .page ; ; Load an overlay from disk, where needed ; 80$: clc ;don't get carried away bit #ss.nal!ss.dsk,(r2) ;if we need to be loaded, are we already ? bne 180$ ;if ne yes bis #ss.dsk,(r2) ;assume we will have success mov 2(sp),r3 ;recall the original R3 = Event Flag mov 4(sp),r4 ;recall the original R4 = IOSB address clr -(sp) ;no sixth qio parameter mov (r2),-(sp) ;isolate the overlay's relative disk - bic #^c,(sp) ;block address for the fifth parameter clr -(sp) ;no fourth qio parameter clr -(sp) ;no third qio parameter mov s.size(r2),-(sp) ;set up the size of the segment to be read mov s.addr(r2),-(sp) ;set up the virtual address to write to mov r5,-(sp) ;use the caller's AST routine, if any mov @#n.ovpt,r5 ;fetch the overlay work area address mov r4,-(sp) ;set up the caller's IOSB address bne 100$ ;if ne the caller did specify one tstb r3 ;did the caller provide an Event Flag, too ? bne 100$ ;if ne yes, use it mov r5,r4 ;copy the work area address add #n.iost,r4 ;point to the work area's IOSB mov r4,(sp) ;use that one in stead of nothing 100$: mov r3,-(sp) ;set up the user's Event Flag bne 120$ ;if ne there is one mov #deflag,(sp) ;otherwise, use one of our own invention 120$: mov n.ovly(r5),-(sp) ;use the LUN from the work area mov #io.lov,-(sp) ;ask the loader to treat us special dir$ #qio ;attempt the load bcs 140$ ;if cs the system didn't like our call tstb r3 ;are we using our own Event Flag ? bne 180$ ;if ne no, let the caller do the rest wtse$s #deflag ;otherwise, wait for the load to complete tstb (r4) ;did everything go okay ? bpl 180$ ;if pl yes 140$: bic #ss.dsk,(r2) ;tell ourself we aren't loaded from disk 160$: bis #ss.nld,(r2) ;so much for our assumptions sec ;advertise our disappointment 180$: return .end