.title Ovctl .ident /X12.01/ ;+ ; **-Ovctl-Overlay control routines for unloading and loading segments ; for tasks with no memory-resident overlays ; ; Version X12.01 ; ; Wayne E. Baisley June 2, 1982 ; ; This module contains two routines: ; ; 1) $Marks - Find and unload 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 a specified segment ; ; Inputs: ; ; R2=Overlay segment descriptor address for segment which is to be loaded ; R3=Optional event flag number for the Load Overlay QIO ; R4=Optional I/O Status Block address for the Load Overlay QIO ; R5=Optional AST routine address for the Load Overlay QIO ; ; 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 | ; +-------------------------------+ ; ; * - The Segment Name is appended only if the manual load routine ; ($Load) is used. ; ; 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 (Not used in this case) ; 10000 = (ss.nld) Segment is not loaded ;- .mcall alodf$, filio$ .mcall dir$, wtse$s alodf$ ;define the segment descriptor symbols filio$ ;define the QIO 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 $marks:: mov r2,-(sp) ;save R2, the segment descriptor address ; ; Trace back all loaded segments for this window ; 40$: bit #ss.nld,(r2) ;is this segment loaded ? 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 ; ; Unload a conflicting segment and all its subordinates ; 140$: bit #ss.nld,(r2) ;is this segment loaded ? bne 120$ ;if ne no, look at another neighbor bis #ss.nld,(r2) ;otherwise, unload it. Simple, no ? mov s.lkup(r2),(sp) ;having found a loaded 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, unload 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 loading clc ;don't get carried away bit #ss.nal,(r2) ;is there an allocation for this segment ? bne 180$ ;if ne no, skip it ; ; Set up the Load Overlay QIO Parameter Block ; 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 ; ; Execute the QIO and clean up ; 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$: 160$: bis #ss.nld,(r2) ;so much for our assumptions sec ;advertise our disappointment 180$: return .end