DataMuseum.dk

Presents historical artifacts from the history of:

Bogika Butler

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Bogika Butler

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦75e9ae17b⟧ TextFile

    Length: 20224 (0x4f00)
    Types: TextFile
    Names: »IMMUPROC.PAS«

Derivation

└─⟦08e5746f0⟧ Bits:30009789/_.ft.Ibm2.50007359.imd Mogens Pelles Zilog 80,000 / EOS projekt
    └─⟦this⟧ »IMMUPROC.PAS« 

TextFile

   PROCEDURE InitMMU;

      (* The MM_Proc initialization gets control right after the preface

         The following steps are carried out:

         (1) Allocate page table
         (2) Set up initial mem-rec structure
         (3) Boot loaded modules (in ram) are described as one segment object
         (4) Create the fulspace segment object and initial pointers
         (5) Allocate and initialize the stub object, except local pointers
         (6) Create the boot owner set, describing the boot loaded modules
             in local-2 of the stub object
         (7) Initialize local-1: Ref to the code of the stub
                        local-6: ref to the fulspace segment object
         (8) Create the alloc object

      *)


      PROCEDURE MMBusErr;

         (* Bus_error_exception may be generated by illegal address
            specifications in the ram area list *)

        BEGIN (* MMBusErr *)
         Error(0);
        END;  (* MMBusErr *)

      FUNCTION Get_LdMd: AddressType;

         (* Return address of boot loaded modules *)

        BEGIN (* Get_LdMd *)
         Get_LdMd := AllocObj.Se_fir
        END;  (* Get_LdMd *)

      FUNCTION Get_StMd: AddressType;

         (* Return the stub module address *)

        BEGIN (* Get_StMd *)
         IF KV_Stub = -1 THEN
            Get_StMd := Get_LdMd
         ELSE
            Get_StMd := KVStub
        END;  (* Get_StMd *)

      FUNCTION GetStubE: AddressType;

         (* Get address of the stub envelope *)

        BEGIN (* GetStubE *)
         GetStubE := KV_IManP.Common.Pointer.Next (* First env. in list *)
        END;  (* GetStubE *)

      FUNCTION GetStubO: AddressType;

         (* Get address of the stub object *)

        BEGIN (* GetStubO *)
         GetStubO := KV_IOwnP.Common.Pointer.Next (* First obj. in list *)
        END;  (* GetStubO *)

      PROCEDURE MakeSegm(
         UserSize: LongInteger;    (* Length of user part (D1) *)
         UserAddress: AddressType; (* Address of user part (A1) *)
         SegmentObject: NonEmbeddedSegmentObjectType
                                   (* Address of kernell part (A0) *)
                        );

         (* Make a non embedded segment object *)

         VAR
            d0: AddressType;      (* Top address of user part =
                                     UserAddress + UserSize *)
            Dummy: AddressType;

        BEGIN (* MakeSegm *)
         (* prt_reg(parameters) *)

         d0 := UserAddress + UserSize;
         IF d0 IN (. F_Alloc..L_Alloc .) THEN
            PgTabSet(d0, KernelAddress);   (* PageTable(d0):=KernelAddress *)
         WITH SegmentObject DO
           BEGIN
            WITH CommonPart DO
              BEGIN
               OB_Kin := OB_SEOB;  (* Kind := segment object *)
               OB_Sta := OB_SEGM;  (* State := segment *)
              END;
            WITH SegmentPart DO
              BEGIN
               SE_io := 0;         (* io_count := 0 *)
               SE_Fir := UserAddress;
               SE_Len := UserSize;
               InitHead(SE_Wait, Dummy);
              END;
            WITH SpacePart DO
            (* Possibly this should be handled dynamically so that SpacePart
               could be positioned anywhere. See line 1260 in MMPROCS.SA
               Something like WITH CommonPart.OB_Spa^ DO *)
              BEGIN
               SP_FirU := UserAddress;
               SP_FreU := 0;
               SP_SizU := UserSize;
               SP_FirK := SP_FirK + (SE_Siz - OB_Siz); (* Add size of SegmentPart *)
               SP_FreK := SP_FreK - (SE_Siz - OB_Siz);
              END;
           END;
(*
          prt_mem('Makesegm', SegmentObject, AllocSiz);
*)
        END;  (* MakeSegm *)

      VAR
         d1: integer; (* Allocation Space *)
         d2: integer; (* Page Table Size *)

         Inx: integer; (* MemList index *)
         Curr: integer; (* Current mem rec *)
         Prev: integer; (* Previous mem rec *)
         Next: integer; (* Next mem rec *)
         FFre: integer; (* First free byte *)
         TFre: integer; (* Top free byte *)

         Holder: MemRecPointerType; (* ^Holder mem rec of loaded modules *)
         CMRPtr: MemRecPointerType; (* ^Current mem rec *)
         CLMPtr: LdMdHeaderPtrType; (* ^Current load module *)
         TopModuleAddress: AddressType; (* Highest addr. in modules *)
         TopModuleSize: Integer; (* Size of loaded modules *)

         ObjDscPtr: LdMdObjectDescriptionPtrType;
            (* ^Program object descriptor *)
         KernelPart: AddressType; (* Address of kernel part of object *)
         UserPart: AddressType;   (* Address of user part of object *)
         Size: integer;           (* Size of primary envelope *)
         Envelope: AddressType;   (* Address of envelope *)
         SpaceDsc: AddressType;   (* Address of space descriptor *)

         LDSD_Inx: word;  (* Local data segment descriptor index *)
         LSD_Inx: word;   (* Load section descriptor index *)
         SegmentSize: integer; (* Size of segment *)
         Rest: integer;   (* Remaining size of protected modules *)
         ObjDscAddr: AddressType; (* Addr. of program object descriptor *)
         LDSDAddr: AddressType; (* Addr. of local data segment descriptor *)
         LSDAddr: AddressType; (* Addr. of load section descriptor *)


     BEGIN (* InitMMU *)

      (**** The bus error exception handler gets control if a non
            existing address or uneven address is referenced by the
            MMproc initialization phase *)

      KV_InVec(.2.) := addr(MMBusErr); (* Bus error vector*)
      KV_InVec(.3.) := addr(MMBusErr); (* Address error vector*)

      (**** Format the last part of the last ram area:
            Compute the addresses of:
            Page_Tab, L_Alloc, F_Alloc, F_Supvs, SupvStk *)

      WITH Mem_List (* pointed to by KV_FrMem *) DO
        BEGIN
         d1 := List(.Length.).End - List(.1.).Start;
         IF d1 <= 0 THEN
            Error(3)
        END;

      (**** The page table need not describe the memory holding
            the page table. The table contains 4 bytes for each
            page of 256 bytes, consequently:

            TABSIZE * 64 + TABSIZE = ALLOCSPACE

            <=>

            TABSIZE = ALLOCSPACE DIV 65

            Divide allocspace with 65;
            Tabsize may be larger than 2*16, hence simple
            division is insufficient *)

       d2 := 0;                    (* tabsize *)
       WHILE d1 > 65*65000 DO
         BEGIN
          d1 := d1 - 65*65000;
          d2 := d2 + 65000;
         END;
      d2 := (d2 + d1 DIV 65) + 7; (* round up by 7 *)
      IF odd(d2) THEN
         d2 := d2 - 1;            (* tabsize must be even *)

      WITH Mem_List DO
         d1 := (List(.Length.).End - d2) DIV 256 * 256;
      (* d1 = ( top of last ram area - tabsize ) truncated to page boundary *)

      L_Alloc := d1;  (* L_Alloc := last mem_rec *)
      Supv_Stk := d1; (* Top byte of Supv_Stk := L_Alloc *)

      (**** Set up the supervisor stack. Subroutines may now be called *)

      (*
         Subroutines called so far (this is a subroutine) have been using
         the initial supervisor stack pointer Init_SSP based at RAM_TOP.
         Init_SSP is boot loaded into the exception vector area.
         Will this stack be overwritten during initialization??

      *)

      (* stack pointer register "a7" := d1; *)
      F_Supvs := (d1 - KV_StkSiz) DIV 256 * 256;

      (**** The variable called page_tab should contain the address of
            entry # 0 of the page table and not the address of entry # 1 *)

       WITH Mem_List DO
         BEGIN
          Page_Tab := List(.Length.).End - d2 - List(.1.).Start DIV 256 * 4;
          F_Alloc :=  List(.1.).Start;
         END;
(*
      Prt_Mem('F_Alloc_etc', F_alloc, MM_Queue-F_Alloc);
*)

      (**** Set up initial mem_recs *)

      FOR Inx := 1 TO Mem_List.Length DO
         WITH Mem_List.List(.Inx.) DO
           BEGIN
            FFre := Start;
            IF Inx = 1 THEN
              BEGIN
               FFre := Start + MR_Siz;
               Curr := Start;
               Prev := FFre; (* Bad trick WIR says *)
              END;
            TFre := (End - MR_Siz) div 256 * 256;
            Next := TFre;
            IF Inx = Mem_List.Length THEN
              BEGIN
               TFre := F_Supvs;
               Next := L_Alloc;
              END;
            IF Curr >= TFre THEN
               Error(4);
            NewHead(Curr, User, Prev, Next);
            WITH MemRecPtr(Curr)^ DO
              BEGIN
               MR_Fst := FFre;
               MR_Fre := TFre - FFre;
              END;
(*
            Prt_Mem('NewHead', Curr, MR_Siz);
*)
            Prev := Curr;
            Curr := Next;
           END;

      (**** Curr = Last mem rec. Prev = mem rec holding supervisor stack
            adjust these mem rec.
            Assign known but illegal addresses to undefined chain fields *)

      WITH MemRecPtr(Curr)^ DO
        BEGIN
         MR_Prv := MemRecPtr(Prev);    (* last mem rec.prev := prior mem rec *)
         MR_Nxt := MemRecPtr(10#4711); (* next to last := odd address *)
         MR_Fix := Initial;  (* L_Alloc.fix := initial *)
         MR_Fre := 0;       (* L_Alloc.Free_Bytes := 0 *)
(*
         Prt_Mem('LastHead', Curr, MR_Siz);
*)
        END;

      MemRecPtr(Prev)^.MR_Typ := User;

      MemRecPtr(F_Alloc)^.MR_Prv :=
         MemRecPtr(10#7913) ; (* prior to first := uneven address *)
(*
      Prt_Mem('FirstHead', F_Alloc, MR_Siz);
*)

      (**** Create one segment object that has the boot loaded modules as
            segment data. This will protect the modules during the
            initialization. The AllocObj is used as the kernel part of this
            segment object *)

      IF KV_BotLd <> -1 THEN (* Modules have been boot loaded *)
        BEGIN
         (**** Find the mem rec that holds the boot loaded modules. This
               mem rec is called holder. The modules must be present in one
               of the mem recs. The modules may have been damaged by the
               previous initialization if they were located too near to the
               end (or beginning) of the ram area that holds the modules *)

         CMRPtr := MemRecPtr(F_Alloc); (* First mem rec *)
         REPEAT
            Holder := CMMRPtr;
            CMRPtr := CMRPtr^.MR_Nxt
         UNTIL PtrVal(CurrPtr) > KV_BotLd;

         (****  Find length of boot loaded modules *)
         TopModuleAddress := KV_BotLd + 256; (* including the zero module *)
         CLMPtr := LdMdPtr(KV_BotLd);
         REPEAT
            TopModuleAddress := TopModuleAddress + CLMPtr^.MOD_Size
         UNTIL CLMPtr^.MOD_Size = 0; (* Size of dummy top module = 0 *)

         (**** Restructure holder^. Create MemRec at TopModuleAddress *)
(*
         Prt_reg('BootModule', **local variables ** *);
*)
         IF TopModuleAddress mod 256 <> 0 THEN
            Error(1);
         ModuleSize := TopModuleAddress - KV_BotLd;
         IF ModuleSize mod 256 <> 0 THEN
            Error(2);
         IF ModuleSize > 256 THEN
            ReChainC(Holder^, KV_BotLd, ModuleSize, User)
        END
      ELSE  (* No boot loaded modules *)
         ModuleSize := 0;
      InitKnel(AllocObj, AllocSiz);
      IF ModuleSize > 256 THEN
         MakeSegm(ModuleSize, KV_BotLd, AllocObj);

      (**** Create Fulspace Object *)
      InitKnel(FulSpace, NEmb_Siz);
      MakeSegm(16#1000000, 0, FulSpace);

      (**** Initial Pointer Init *)
      WITH KV_IOwnP.Common DO
        BEGIN
         WITH Pointer.Chain DO
           BEGIN
            Next := ChainPtr(addr(KV_IOwnP));
            Prev := ChainPtr(addr(KV_IOwnP))
           END;
         PT_Inf := PT_lsc;
        END;

      WITH KV_IManP.Common DO
        BEGIN
         WITH Pointer.Chain DO
           BEGIN
            Next := ChainPtr(addr(KV_IManP));
            Prev := ChainPtr(addr(KV_IManP))
           END;
         PT_Inf := PT_lsc;
        END;

      (**** Various global variables *)
      MM_Lock := open;
      WITH MM_queue DO  (* := empty *)
        BEGIN
         Next := ChainPtr(addr(MM_queue));
         PRev := ChainPtr(addr(MM_queue))
        END;

      CurKMove := 0;  (* Clear move candidate *)

      (**** Allocate Stub Object. The Stub module can be found in KV_Stub
            (Stub in ROM) or (when KV_Stub = -1) in allocObj.SE_fir
            (Stub in RAM). *)

      ObjDscPtr: = LdMdObjDscPtr(Get_StMd +
                                       LdMdHdrPtr(Get_StMd)^.MOD_Prog
                                      );
      WITH ObjDscPtr DO
        BEGIN
         IF MOD_Locs < 10 THEN  (* If #local pointers < 10 then error *)
            Error(8);
         Size := (MOD_Locs*Pt_Siz)+SP_Siz+GE_Siz+EN_Siz;
         MM_Cre(Size, 0, KernelPart, UserPart);
         IF false THEN  (* Compare with line 2190 of mmprocs.sa *)
            Error(5);
        END;

      (**** Initial owner pointer holds the stub as the first member *)
      ChainOwn( KernelPart, KV_IOwnP, 0 (*, omitting a2 *) );

      (**** Create primary envelope *)
      Size := Size - SP_Siz - GE_Siz;
      MM_PushK(KernelPart, Envelope, Size, SpaceDsc);
      Init_Env(Size, Envelope, SpaceDsc);

      (**** Initial manager pointer holds the stub envelope as first member *)
      ChainMan( Envelope, KV_IManP, 0 (*, omitting a2 *) );

      (**** Initialize general part of stub object *)
      InitGein(PtrVal(Get_StubO), ObjDscPtr^.MOD_Ent);

      (**** Modify the stub object according to the description *)
      WITH GePtr(Get_StubO)^.GeneralPart, ObjDscPtr^ DO
        BEGIN
         GE_Temp := MOD_Temp + 1; (* including T(0) *)
         GE_Stk := MOD_Stk;  (* Sizetype *)

         (* Push MOD_Stk on stack to be picked up when boot process is
            created *)
(* *** ??? *** *)
         GE_TemD := MOD_TemD
        END;

   (**** Create a set of non embedded segment objects.
         Each segment object contains a header segment or a load section
         from the boot loaded modules currently protected by the alloc
         object.The segment data of the alloc object shrinks as the new
         set grows. The set is owned by local-2 oof the stub object.
         The header sections as well as the load sections must be an integral
         number of pages *)

   IF KV_BotLd <> -1 THEN
      REPEAT
         WITH LdMdHdrPtr(Get_LdMd)^ DO
           BEGIN
(*
            PrtMem('HeaderSection', Get_LdMd, 300 );
*)
            (* Move the size of the header section and of the associated
               load sections to the stack *)

            (* Save old stack pointer a7 in a6 *)
            Rest := MOD_Size;
            TstPage(MOD_HSiz, 6);
            Rest := Rest - MOD_HSiz;
            (*Push MOD_HSiz *)
            ObjDscAddr := Get_LdMd + MOD_prog;
            WITH LdMdObjDscPtr(ObjDscAddr)^ DO
              BEGIN
               LDSDAddr := ObjDscAddr + MOD_FDSD;
               FOR LDSD_Inx := 1 TO MOD_LDSS DO
                 BEGIN
                  WITH LdMdLDSDPtr(LDSDAddr)^ DO
                    BEGIN
                     LSDAddr := LDSDAddr + MOD_LDSz;
                     FOR LSD_Inx := 1 TO MOD_LSDS DO
                        WITH LdMdLSDPtr(LSDAddr)^ DO
                          BEGIN
                           TstPage(MOD_Slen,6);
                           Rest := Rest - MOD_Slen;
                           (* Push MOD_Slen *)
                           LSDAddr := LSDAddr + MOD_LSDZ
                          END;
                     LDSDAddr := LDSDAddr + MOD_DSiz;
                    END
                 END
              END;
            IF Rest <> 0 THEN
               Error(7);
            (* Push saved old stck pointer in a6 onto stack *)

            (* The stack now contains a word and a number of longs.
               Create segment objects according to these values. *)

            (* items are read from the stack bottom i.e. in the
               sequence they were pushed *)

            (* SegmentSize := signextend(unpush(a6)); *)
            REPEAT
               MM_Cre(NEmb_Siz, 0, KernelPart, UserPart);
               IF false THEN
                  Error(8);
               (**** Remap data into new object *)
               MakeSegm(SegmentSize, Get_LdMd, KernelPart);
               (**** Remove data from the protecting alloc segment *)
               WITH AllocObj DO
                 BEGIN
                  SE_Fir := SE_Fir + SegmentSize;
                  SE_Len := SE_Len - SegmentSize;
                  WITH SpaceDscPtr(OB_Spa)^ DO
                    BEGIN
                     SP_FirU := SP_FirU + SegmentSize;
                     SP_SizU := SP_SizU - SegmentSize;
                    END
                 END;
(*
               PrtMem('Unprotect', AllocObj, AllocSiz);
*)
               (**** Chain new segment object to local-2 of stub object *)
               ChainOwn(KernelPart, Get_StubE, EN_Siz+PT_Siz (*,omitting a2*));
               (* SegmentSize := unpush(a6) size of next segment *)
            UNTIL (* a6 = a7 *);
            (* Restore old stak pointer a7 := a6; *)


           END
         UNTIL LdMDHdrPtr(Get_LdMd)^.MOD_Size = 0 (* zero module is reached *);
         IF AllocObj.SE_Len <> 256 THEN
            Error(7);  (* Module jam *)
         RemoveUS(AllocObj.SE_Len, Get_LdMd);

      (**** Set up program ref in local-1 of stub *)
      IF KV_Stub <> -1 THEN  (* Stub module in ROM *)
        BEGIN
         (* Create a subsegment of the fulspace segment describing the local
            sections of the module *)

         MM_Cre(SU_Siz+SP_Siz, 0, KernelPart, UserPart);
         WITH LdMdHdrPtr(KV_Stub)^, SuPtr(KernelPart)^ DO
           BEGIN
            WITH CommonPart DO
              BEGIN
               OB_Kin := OB_SEOB;
               OB_Sta := OB_SUB;
              END;
            WITH SegmentPart DO
              BEGIN
               SE_Io := 0;
               SE_Fir := KV_Stub + MOD_HSiz;
               SE_Len := MOD_Size - MOD_HSiz;
               InitHead(SE_Wait, DummyAddr);  (* Make list empty *)
              END;
            ChainOwn(KernelPart, GetStubE, EN_Siz);

            (**** Let the segment pointer of the subsegment point to
                  the fulspace segment object *)
            WITH SubSegmentPart DO
              BEGIN
               SimplePt(SU_P, FulSpace);
               SU_P.Common.PT_Kin := PT_Seg
              END
           END
        END
      ELSE
         (* The stub is in RAM. The second object in the owner set
            of local-2 of the stub will be the code segment. Create a
            simple pointer to that object *)
         SimplePt(PointerPtr(EN_Siz+GetStubR)^,
                  SePtr(PointerPtr(EN_Siz+PT_Siz+GetStubE)^.Next)^);

      (**** Local-6 of the stub envelope should point to the fulspace
            object *)
      SimplePt( PointerPtr(EN_Siz+5*PT_Siz+GetStubE)^, FulSpace9;

      (**** Initialize the AllocObj as the initila alloc object
            of the kernel *)
      InitKnel(AllocObj, AllocSiz);
      WITH AllocObj.Common DO
        BEGIN
         OB_Kin := OB_Allo;
         OB_Sta := (.OB_Reen.);
(*
         PrtMem('FinalAlloc', AllocObj, AllocSiz);
*)
        END;

      (**** Local-3 of the stub should point to the AllocObj *)
      SimplePt(PointerPtr(EN_Siz+2*PT_Siz+GetStubE)^, AllocObj);

      (**** Locals 4,5,7,8, and 9 are initialized b the scheduler,
            local  10 by enter. *)

(*
      PrtMem('EndOfMMprocs', (a7), 8)
*)
     END;  (* InitMMU *)

«eof»