// A L T O E X E C U T I V E // Internal Exec Commands (1) - Type.bcpl // Copyright Xerox Corporation 1979, 1980 // E. McCreight // last edited by R. Johnsson May 22, 1980 8:26 AM get "sysdefs.d" get "altofilesys.d" get "disks.d" get "streams.d" get "COMSTRUCT.bcpl" external [ TYPE DELETE RELEASE UserBootFrom EBoot Ftp Chat Scavenger NetExec Install Resume BootKeys StandardRam MesaBanks ] let RELEASE(ISTREAM, DSTREAM) be [ WRITE(ExecRelease) WRITE(ReleaseString) ] and TYPE(ISTREAM, DSTREAM) be [ let FN = vec 200 let T = nil SetupReadParam(FN, 0, ISTREAM, FN) while ReadParam($P, -1, FN) ne -1 do [ T = 0 let FILE = MyOpenFile(FN, ksTypeReadOnly, charItem) test FILE eq 0 ifnot [ let DPLen = vec 2 let FL = vec 20 FileLength(FILE, DPLen) test DPLen!0 ne 0 ifnot FORMAT(FL, "", DPLen!1) ifso FORMAT(FL, "", ((DPLen!0 lshift 1)+ (((DPLen!1 & #100000) eq 0)? 0, 1)), DPLen!1 & #77777) PagedWrite( FORMATN("*300Contents of file *301: (Length = (octal) bytes)*N*N", FN, FL), true, lv T) Resets(FILE) until Endofs(FILE) do [ T = PagedWrite(Gets(FILE), true, lv T) if T ne 0 then break ] PagedWrite($*N, true, lv T) Closes(FILE) ] ifso [ PagedWrite("File ", true, lv T) PagedWrite(FN, true, lv T) PagedWrite(" doesn't exist.*N", true, lv T) ] if T eq CONTROLC then break ] return ] and PagedWrite(C, PageBreaks, ResultOfPageBreak) be [ let T = WRITE(C, PageBreaks) if @ResultOfPageBreak eq 0 then @ResultOfPageBreak = T ] and DELETE(ISTREAM, DSTREAM) be [ let FN = vec 200 let SWVEC = vec 200 SetupReadParam(FN, SWVEC, ISTREAM, SWVEC) let PAUSESW = false let WipeIt = false for I=1 to SWVEC!0 do switchon SWVEC!I into [ case $P: case $p: PAUSESW = true endcase default: endcase ] let T = 0 while (T eq 0) & (ReadParam($P, -1, FN) ne -1) & not Cancel() do [ MAKETIMELINE() unless PAUSESW do RESETPAGE() let did = DeleteFile(FN) T = WRITE(FORMATN( (did? "File deleted.*N", "File doesn't exist.*N"), FN ) ) if did then WipeIt = true ] if WipeIt then WIPEDIRBLK() return ] and CheckEther() = valof [ if (StartIO(0)Ź) eq #377 then [ WRITE("This Alto has no Ethernet!*n") resultis false ] WriteDiskDescriptor() resultis true ] and EBoot(IStream, DStream) be [ if not CheckEther() then return let FN = vec 200 let SWVEC = vec 200 SetupReadParam(FN, SWVEC, IStream, SWVEC) FN!0 = 0 ReadParam($P, -1, FN) let v = 0 for i = 1 to FN>>STRING.length do [ let c = FN>>STRING.char^i if c ge $0 & c le $7 then v = v * 8 + (c-$0) ] if CheckEther() then EtherBoot(v) ] and Ftp(IStream, DStream) be [ if CheckEther() then EtherBoot(2) ] and Chat(IStream, DStream) be [ if CheckEther() then EtherBoot(7) ] and Scavenger(IStream, DStream) be [ if CheckEther() then EtherBoot(3) ] and NetExec(IStream, DStream) be [ if CheckEther() then EtherBoot(#10) ] and DIAGNOSE(IStream, DStream) be [ let FP = vec lFP let FoundIt = BootFP(0, "DMT.BOOT", FP) WriteDiskDescriptor() test FoundIt ifso BootFrom(FP) ifnot EtherBoot(0) ] and UserBootFrom(IStream, DStream) be [ let FP = vec lFP let FoundIt = BootFP(IStream, "SYS.BOOT", FP) WriteDiskDescriptor() if FoundIt then BootFrom(FP) ] and Install(IStream, DStream) be [ let FP = vec lFP let FoundIt = BootFP(IStream, "SYS.BOOT", FP) let V = vec lInLdMessage V>>EVM.type = eventInstall V>>EVM.length = 1 V!1 = 0 // last event WriteDiskDescriptor() if FoundIt then InLd(FP, V) ] and Resume(IStream, DStream) be [ let FP = vec lFP let CFA = vec size CFA/16 let FoundIt = BootFP(IStream, "SWATEE", FP, CFA) if FoundIt then [ WriteDiskDescriptor() PatchForSwat(lv (CFA>>CFA.fp)) InLd(FP) ] ] //Before resuming a file, it is considered polite to patch in the // file pointers for the Swat and Swatee on the disk we are running // with -- it may happen that the file we are about to resume was // copied from another disk. So we flail around a bit and do that. and PatchForSwat(fp) be [ structure SCM: [ blank word // For entry point jmp Location word // address of this spot (to find it!) Version word // Version number Why word // Why (0 = break, 1 = interrupt) Swatee word 5 // Fid for Swatee Swat word 5 // Fid for Swat CallSwat word // = #77400 - break here CallArgs word // Here is where you plant the #args CallReturn word // =#77400 - patch subr calls to return here // CodeVector word CodeVectorLength ] // The following procedure positions a file for addressing word w // in an OutLd-format file: let SPW(s, w) be [ let pn = (w rshift 8) if pn eq 0 then pn = 255 if pn eq 1 then pn = 254 PositionPage(s, pn) PositionPtr(s, (wŹ) lshift 1) // New style only!!! ] let s = OpenFile(0,ksTypeReadOnly,0,0,fp) if s then [ SPW(s, #567) // Trap vector entry let tb = Gets(s) if tb then [ tb = tb+(offset SCM.Swatee)/16 let scbase = @#567+(offset SCM.Swatee)/16 // Ours! SPW(s, tb) if valof [ for i=0 to lFP*2-1 do if Gets(s) ne scbase!i then resultis true resultis false ] then [ Closes(s) s = OpenFileFromFp(fp) SPW(s, tb) for i=0 to lFP*2-1 do Puts(s, scbase!i) // 2 FP's ] ] Closes(s) ] ] and BootKeys(IStream, DStream) be [ let FP = vec lFP let FoundIt = BootFP(IStream, "SYS.BOOT", FP) unless FoundIt do return let DiskAddress = FP>>FP.leaderVirtualDa WRITE(FORMATN( "Boot disk address is #, or the following keys:*N", DiskAddress)) test DiskAddress eq 0 ifso WRITE("All keys up!*N") ifnot [ let MaskBit = #100000 for BitNo=0 to 15 do [ let MaskBit = #100000 rshift BitNo if (DiskAddress&MaskBit) ne 0 then if WRITE(FORMATN(" ", selecton BitNo into [ case 0: "5" case 1: "4" case 2: "6" case 3: "E" case 4: "7" case 5: "D" case 6: "U" case 7: "V" case 8: "zero" case 9: "K" case 10: "minus" case 11: "P" case 12: "/" case 13: "\" case 14: "lf" case 15: "bs" ]), true) ne 0 then break ] WRITE("*N") ] ] and BootFP(ComCm, DefaultFileName, FP, CFA; numargs na) = valof [ let S = vec 200 let FN = vec 200 let IsFileName = false if ComCm ne 0 then [ SetupReadParam(S, 0, ComCm, S) IsFileName = (ReadParam("P", -1, FN) ne -1) ] unless IsFileName do FN = DefaultFileName let File = MyOpenFile(FN, ksTypeReadOnly, wordItem) if File eq 0 then [ WRITE(FORMATN("File *"*" couldn't be found.*N", FN)) resultis false ] WRITE(FORMATN("File is ...*N", FN)) let LocalCFA = vec size CFA/16 if na ls 4 then CFA = LocalCFA Resets(File) GetCompleteFa(File, CFA) for i=0 to (size FP/16)-1 do FP!i = (lv CFA>>CFA.fp)!i RealDiskDA(sysDisk, CFA>>CFA.fa.da, lv (FP>>FP.leaderVirtualDa)) Closes(File) resultis true ] // Load Ram to send all traps to the Rom and StandardRam() be [ // These two instructions for very ancient microcode writeram(#637, 0, #102640) // trapx: SWMODE writeram(#640, #10, #102637) // :trapx; // These two instructions for Altocode 14 writeram(#645, 0, #102646) // trapx: SWMODE; writeram(#646, #10, #102645) // :trapx; // These two instructions for Altocode 20 and above writeram(#37, 0, #102036) // trap1: SWMODE; writeram(#36, #10, #102037) // :trap1; ] and writeram(addr, hi, lo) be ( table[ #55001 // STA 3 1,2 #35003 // LDA 3 3,2 #61012 // WRTRAM #35001 // LDA 3 1,2 #1401 // JMP 1,3 ]) (hi, addr, lo) and WriteSortedDirectory(IStream, DStream; numargs na) be [ // SYSTEMDIR is readonly let d = vec 1 let len = FileLength(SYSTEMDIR,d)/2 //positions to end if d!0 ne 0 % d!1 ls 0 then return let dir = OpenFileFromFp(fpSysDir) // let dir = OpenFile("NewDir") if dir eq 0 then return let t, elen = nil, nil t<>MYDE.TYPE ne ISFILE then loop elen = lDV + de>>MYDE.S.length/2+1 t<>MYDE.FP,elen-1) count = count + 1 used = used + elen len = len - elen ] t< entries; words used; words free*n", count, used, free)) return ] and MesaBanks(IStream, DStream) be [ let arg = vec 200 let sw = vec 200 let mask = 177777b let setMask = false SetupReadParam(arg, sw, IStream) ReadParam(0,-1) while arg!0 ne 0 do [ setMask = true test sw!0 ne 0 & (sw!1 eq $x % sw!1 eq $X) ifso [ let n = EvalParam(arg,$D,-1) mask = mask & (not (100000b rshift n)) ] ifnot mask = EvalParam(arg,$B,-1) ReadParam(0,-1) ] if mask eq 0 then mask = 177777b mask = mask % 100000b // bank 0 required if setMask then [ mesaBankMask = mask; RememberData(lv mesaBankMask) ] Wss(DStream, FORMATN("Mesa bank mask B.*n", (setMask? "set to", "is"), mesaBankMask)) ]