//		A L T O   E X E C U T I V E
//	Initialization Module - ExecInit.bcpl
// Copyright Xerox Corporation 1979

//	Ed McCreight
//	last edited by R. Johnsson, May 21, 1980  10:40 PM


get "AltoFileSys.d"
get "Streams.d"
get "BCPLFiles.d"
get "COMSTRUCT.BCPL"

external [	// exported to OnceOnly
	ClockWrong
	DiskInfo
	DiskName
	ExecSysErr
	InCaseOfDemise
	NetNumber
	OldUserFinishProc
	OverlayArea
	OverlayAreaSize
	ShowDiskInfo
	SpaceAbove
	SpaceBelow
		// imported from OnceOnly
	OnceOnlyInitCode
	]

static	[
	BLVptr
	ExecCFA
	OverlayArea
	OverlayAreaSize

	DiskInfo		// stream for disk info
	DiskName

	DiskStatus = #522

	NetNumber = 0

	OldSysErr
	OldUserFinishProc


	SpaceAbove
	SpaceBelow

	ClockWrong = false
	]


let Initialize(CFA, blv) = valof

	[ BLVptr = blv; ExecCFA = CFA
	let BQ = OnceOnlyInitCode(CFA)

	// add the space after the overlay area to
	// the zone

	SetEndCode(OverlayArea+OverlayAreaSize)
	let FreeBlockSize = FixedLeft()-StackNeeds
	AddToZone(CZ, GetFixed(FreeBlockSize), FreeBlockSize)
	if ClockWrong then [ SetTime(); MAKETIMELINE() ]
	resultis BQ
	]


and RememberData(lvData) be

	[
	let exec = OpenFile(0,ksTypeReadOnly,wordItem,0,lv ExecCFA>>CFA.fp)
	let dataPos = ((offset SV.statics)/16 + lvData-BLVptr>>BLV.startOfStatics)*2
	let leader = vec 255
	ReadLeaderPage(exec,leader)
	SetFilePos(exec,0,dataPos)
	let old = Gets(exec)
	Closes(exec)
	if old eq @lvData then return
	exec = OpenFile(0,ksTypeReadWrite,wordItem,0,lv ExecCFA>>CFA.fp)
	SetFilePos(exec,0,dataPos)
	Puts(exec,@lvData)
	WriteLeaderPage(exec,leader)
	Closes(exec)
	]


and SetNetNumber(n) be

	[ if NetNumber eq n then return
	NetNumber = n
	ShowDiskInfo(DiskInfo)
	if NetNumber eq 0 then return
	RememberData(lv NetNumber)
	]


and ShowDiskInfo(Stream) be

	[
	let space = BitWidth(Stream,$*S)
	WriteChars(FORMATN(
		"*n--- OS Version <D>/<D> --- Alto <OCT>#<OCT># --- *300<S>*301 --- *300",
		OsVersion, OsVersionCompatible,
		NetNumber, SerialNumber&#377, UserName), 0, Stream)
	until FitsThisLine(Stream,DiskName,space) do
	    [
	    let len = DiskName>>STRING.length
	    if len eq 0 then break
	    DiskName>>STRING.length = len-1
	    ]
	WriteChars(FORMATN("<S>*301 ", DiskName), 0, Stream)
	while FitsThisLine(Stream, $-) do Puts(Stream, $-)
	]


// the following code must sit around all the time in case
// someone "asynchronously" calls it.

 and UserReadOverlay(od) = valof

	[ let ReleaseIt(od) be
		[ unless ReleaseOverlay(od, true) do
			CallSwat("Executive overlay problems")
		]

	LockPendingCode()
	GeneratePresentOverlays(ReleaseIt)
	ReadOverlay(OverlayFirstPn(od), OverlayArea,
		OverlayNpages(od))
	resultis OverlayArea
	]


and ExecSysErr(p1, errCode, p2, p3, p4, p5, p6,
	p7, p8, p9, p10; numargs na) = valof

	[ // One should probably check the error code
	// here, but at least two codes were found which resulted
	// from disk not ready (1101 and 1503) and there
	// might well be more.

	if (@DiskStatus&#40) ne 0	// current disk not rdy
		then EtherBoot(0)
	@lvSysErr = OldSysErr
	let Result = CallWithNArgs(lv OldSysErr, na, p1, errCode,
		p2, p3, p4, p5, p6, p7, p8, p9, p10)
	@lvSysErr = ExecSysErr
	resultis Result
	]


and InCaseOfDemise(FinishCode) be

	[ @lvSysErr = OldSysErr
	@lvUserFinishProc = OldUserFinishProc
	SetKeyboardProc()
	Closes(USERSTR)
	Closes(DiskInfo)
	Closes(TIMESTR1)
	Closes(TIMESTR2)
	ShowDisplayStream(SpaceAbove,DSdelete)
	ShowDisplayStream(SpaceBelow,DSdelete)
	while @lvUserFinishProc ne 0 do
		[ let FinishProc = @lvUserFinishProc
		@lvUserFinishProc = 0
		FinishProc(FinishCode)
		]
	]


and SwappedOut() be

	[ CallSwat("Executive overlay error. OK to proceed.")
	MiniExec()
	]


and STORAGEGONE(X1, X2, X3, X4) be

	[ Wss(dsp, "*NFree storage gone (sometimes caused by ill-formed directory)!")
	if RemCm ne 0 then
		[ Resets(RemCm)
		TruncateDiskStream(RemCm)
		Closes(RemCm)
		RemCm = 0
		]
	MiniExec()
	]


and MiniExec() be

	[ Wss(dsp, "*NEmergency Exec -- Type subsystem name: ")
	let UPS = vec 300
	ReadString(UPS)
	let SubSysName = vec 129
	EvalParam(UPS, $P, 0, SubSysName)
	Wss(dsp, "*NType command line: ")
	ReadString(UPS)
	let ComCm = OpenFile("Com.Cm", ksTypeWriteOnly, charItem)
	for i=1 to UPS!0 do Puts(ComCm, UPS!i)
	Puts(ComCm, $*N)
	Closes(ComCm)
	let SubSys = OpenFile(SubSysName, ksTypeReadOnly, wordItem)
	userParamsVec!0 = 0
	(@lvUserFinishProc)(0)
	CallSubsys(SubSys, false, false, userParamsVec)
	]