//D1I2.BCPL -- machine-dependent part of Init2()
//	11 May 1983

get "mcommon.d"
get "d1.d"
manifest [ get "d1pe.d" ]
manifest [ get "d1regmem.d" ]
manifest [
	IMstablen = (#20000/BlockSize)+1	//Max size for 16K IMX
	RMstablen = (RMlen+1)/2
	BRstablen = (BRlen+1)/2
	TASKNstablen = (NTasks+1)/2
	DEVICEstablen = (DEVICElen+1)/2
]

external [
// OS
	SetBlock; Zero; Resets

// MINIT0
	@ACTS; MStatus; ConnectStream

// MASM
	GetStorage; Wss; @WssCSS; ResetsCSS; ResetsCS1; @MBlock

// MDATA
	MDATAtab; MADDRtab; @BitsChecked; @HighAddress; @AddrIncrement
	MCTimeOut; CheckStoppedGlitches

// MIOC
	Wns

// MMENU
	CreateAction; ItemStream; @WsMarkA; MarkMenus

// MCMD
	WnsCSS; QuitCmdOverlay

// MGO
	@QuitF

// D1I0
	HWStatus

// D1TABLES
	@MEMNAM

// D1MICASM
	@MCXct; MCWaitCnt

// D1ASM
	@DoStrobe; LoadCPReg; @CheckStopped; GetErrs; LoadDMD

// D1RES
	ReadAllRegs

// D1VM
	SetVirtP; IMstab; RMstab; BRstab; TASKNstab; DEVICEstab

// D1GO
	MStopped

// D1MICRES
	ChangeAltoControl

// D1CONFIG
	FixForConfiguration; ShowConnection
	HaveControl; HaveProcL; HaveProcH; HaveMemC
	HaveMemD; HaveMemX; HaveIFU; HaveDskEth; HaveDisplay
	MapICcode; MainICcode; ModuleMask; log2rows
	NoCacheAParity; log2pgsize; IMXmask

// Defined here
	InitHardware; ConfigUnknown; DefMemName
]

static [ ConfigUnknown; DefMemName ]

//Result is 0 or an alternate command menu.
let InitHardware() = valof
[	SetVirtP(false)
	DefMemName = MEMNAM!VMx
//Note:  all implementations of Midas must define the MDATA and MADDR
//memories used in MTEST and MDEBUG.
	Zero(MDATAtab,MDATAlen*3)
	Zero(MADDRtab,MADDRlen*2)
	let Big = table [ -1; -1; 170000B ]
	MBlock(BitsChecked,Big,3)
	SetBlock(HighAddress,-1,2)
	AddrIncrement!1 = 1
//Initialize inverted tables for SearchBlocks
	IMstab = GetStorage(IMstablen); Zero(IMstab,IMstablen)
	RMstab = GetStorage(RMstablen); Zero(RMstab,RMstablen)
	BRstab = GetStorage(BRstablen); Zero(BRstab,BRstablen)
	TASKNstab = GetStorage(TASKNstablen); Zero(TASKNstab,TASKNstablen)
	DEVICEstab = GetStorage(DEVICEstablen); Zero(DEVICEstab,DEVICEstablen)
//Serial number not stored in a static (would be smashed by RunProg)
	ACTS!1 = HWStatus>>HWStatus.ConnectedMachine
	test ACTS!1 eq -1
//Starting Midas from the Exec or not attached to any machine, in which
//case hardware configuration is unknown
	ifso
	[ let ND,T = 1,nil
//Build in ACTS a 4-word item for each connectable Dorado: 1st word
//is the serial number, next two are a decimal string to be used as
//an action in the Dorado select menu.
	  MCWaitCnt = 20	//2 msec wait during polling
	  for N = 0 to 255 if ConnectToD1(N) do
	    [ ACTS!ND = N
	      test N < 8
	      ifso ACTS!(ND+1) = 460B+N	//1 char string
	      ifnot test N < 64
		ifso			//2 char string
		[ ACTS!(ND+1) = 1060B+(N/8)
		  ACTS!(ND+2) = (60B+(N rem 8)) lshift 8
		]
		ifnot			//3 char string
		[ ACTS!(ND+1) = 1460B+(N/64)
		  T = N rem 64
		  ACTS!(ND+2) = 30060B+((T/8) lshift 8)+(T rem 8)
		]
	      ND = ND+4
//Give up if more than 20 Doradoes possible
	      if ND > 20*4 then break
	    ]
	  ACTS!0 = (ND-1)/4
	  switchon ACTS!0 into
	  [
//More than one--show menu and let user choose
default:    for I = 1 to ND-4 by 4 do
	    [ ACTS!(I+3) = CreateAction(ACTS+I+1,lv ConnectAction,ACTS!I)
	    ]
	    ACTS!(ND+3) = CreateAction("NoHW",lv ConnectAction,-1)
	    resultis FindDorado
//Exactly one Dorado--connect to it.
case 1:
//No Doradoes--come up in Midas test mode, faking a connection
case 0:	    endcase
	  ]
//Fire up read/write parts of Midas only when selected Dorado
//is halted; if running, menus should come up like they do in a "Go".
//*Note:  configuration cannot be determined when Dorado is running
//because Dorado controls the muffler system when SetRun is true.
	  NewConnect(ACTS!1)
	]
//Doing RunProg, in which case hardware configuration is recorded in
//HWStatus which must be unpacked.  It is impossible for the machine
//to be running here.
	ifnot
	[ HaveControl = HWStatus>>HWStatus.HaveControl ne 0
	  HaveProcL = HWStatus>>HWStatus.HaveProcL ne 0
	  HaveProcH = HWStatus>>HWStatus.HaveProcH ne 0
	  HaveMemC = HWStatus>>HWStatus.HaveMemC ne 0
	  HaveMemD = HWStatus>>HWStatus.HaveMemD ne 0
	  HaveMemX = HWStatus>>HWStatus.HaveMemX ne 0
	  HaveIFU = HWStatus>>HWStatus.HaveIFU ne 0
	  HaveDskEth = HWStatus>>HWStatus.HaveDskEth ne 0
	  HaveDisplay = HWStatus>>HWStatus.HaveDisplay ne 0
	  ConfigUnknown = HWStatus>>HWStatus.ConfigUnknown ne 0
	  MapICcode = HWStatus>>HWStatus.MapICcode
	  MainICcode = HWStatus>>HWStatus.MainICcode
	  ModuleMask = HWStatus>>HWStatus.ModuleMask
	  log2rows = HWStatus>>HWStatus.log2rows
	  NoCacheAParity = HWStatus>>HWStatus.NoCacheAParity
	  log2pgsize = HWStatus>>HWStatus.log2pgsize
	  IMXmask = HWStatus>>HWStatus.IMXmask
	  MakeConnection(ACTS!1)
	  FixForConfiguration()
	  ReadAllRegs(0)
	]
	ShowConnected(ACTS!1)
	resultis 0
]


and ShowConnected(N) be
[	Resets(ConnectStream)	//Probably unnecessary
	test N eq -1
	ifso Wss(ConnectStream,"Disconnected")
	ifnot
	[ Wss(ConnectStream,"Serial #")
	  Wns(ConnectStream,N,0,8)
	]
]


and ConnectToD1(N) = valof
[	MCTimeOut!0 = 0
	LoadCPReg(BSelD+BCNoop+N); DoStrobe(Clock+BaseBAtten)
//MCXct returns 0 on success, -1 on timeout
	resultis not MCXct(BInt+BCNoop)
]


and ConnectAction(N,nil,nil) be
[	NewConnect(N); ShowConnected(N); QuitCmdOverlay()
]


and NewConnect(N) be
[	let ConnectedOK = N ne -1 ? ConnectToD1(N),true
//Set HaveControl true so that the first few calls to CheckStopped will
//not be distorted--when HaveControl is false, CheckStopped always returns
//"running."
	ConfigUnknown,HaveControl = true,true
	test MakeConnection(N)
	  ifso if ConnectedOK do	//Running
	  [ ShowConnection(); WssCSS(", running")
	  ]
	  ifnot if ConnectedOK do	//Halted--print like breakpoint
	  [ QuitF = -1; MStopped(false)
	  ]
	unless ConnectedOK do
	[ MStatus>>MStatus.MachRunning = true
	  ResetsCSS(); ResetsCS1()
	  WssCSS("**Serial #"); WnsCSS(N)
	  WssCSS(" connection failed** ")
	]
]


and MakeConnection(N) = valof
[	ChangeAltoControl(BAltoControl+BCNoop+1)
	HWStatus>>HWStatus.ConnectedMachine = N
//Fill out some of HWStatus vector also written by D1Reset; can't do
//everything unless Dorado is halted because the mufflers can't be
//read while SetRun is true, and don't want to halt it if it is running.
	CheckStoppedGlitches!0 = 0
	let MachRunning = not CheckStopped()
	MStatus>>MStatus.MachRunning = MachRunning
//MIRdebugging is used with LoadDMD(IMAddr2) operations and for
//CantContinue indication
	HWStatus>>HWStatus.MIRdebugging =
		(GetErrs() & MIRDebugena) ne 0 ? MIRdebug,0
	resultis MachRunning
]


//Put up connection menu
and FindDorado(S,nil) be
[	let ND = 1
	Wss(ItemStream,"Select Dorado: "); MarkMenus(0)
	for I = 1 to (ACTS!0)+1 do
	[ WsMarkA(ACTS!(ND+3)); ND = ND+4
	]
	return
]