// DiExStatus.bcpl


get "DiEx.defs"


static @CurrentDr
manifest noStat = -1

let DisplayStatus() be
	[ Active = false
	DisplayParam(ListETable, 0, Tab3)
	DisplayParam(GetStatus, 0, Tab2)
	DisplayParam(DoRestore, 0, Tab1)
	DisplayParam(ResetET, 1, Tab0)
	DisplayParam(Chain, 8, Tab3)
	]

and GetStatus() be
	[ external TP2
	if Returns eq 0 then CurrentDr = FirstDr
	let status = nil
	let last1 = Button(Left%Middle,Up)
	if Active then
		test last1
			ifnot return
			ifso [  SelectDrive(CurrentDr,false); status = DiskStatus()
				if last1 eq Left then break
				Wait(1000)
				if Button(Left%Middle,Down) then break
				] repeat
	//unless status<<DST.sector eq #17 then 
	[ CurrentDr = CurrentDr ls LastDr? CurrentDr+1,FirstDr ]
	PrintParam("Print Status")
	]

and DoRestore() be
	[ SendHint("Middle button will invoke repeated restores until left button")
	if Returns eq 0 then CurrentDr = FirstDr
	let last1 = Button(Left%Middle,Up)
	if Active then
		[ test last1
			ifnot return
			ifso [ SelectDrive(CurrentDr,true)
				if last1 eq Left then break
				Msg("↑")
				Wait(50)
				if Button(Left%Middle,Up) then [ Msg("*n>>"); break ]
				] repeat
		DiskStatus() 
		//unless status<<DST.sector eq #17 then 
			[ CurrentDr = CurrentDr ls LastDr? CurrentDr+1,FirstDr ]
		]
	PrintParam("Restore Disk")
	]

and Chain() be
	[
	if NewBoolian("Chain disk commands for full speed operation. - no chaining for testing bad hardware") then T>>P.Chain = T>>P.Chain eq 0
	PrintParam("Chain: $S",T>>P.Chain?"Yes","No")
	]

and ListETable(Print,FT) be
	[
	if Returns eq 0 then CurrentDr = FirstDr
	if NewBoolian("Print contents of Error Table") then
		[ ListET(CurrentDr); CurrentDr = CurrentDr ls LastDr? CurrentDr+1,FirstDr ]
	PrintParam("List E.T.")
	]

and ResetET(Print,FT) be
	[
	if NewBoolian("Clear contents of Error Table",true) then 
		[ initCounters(); Hint("Done") ]
	PrintParam("Reset E.T.")
	]

and ResetDisk(restore) be
	[ external [ Idle; InitializeCbStorage; GetCb; DoDiskCommand ]
	let CA = vec 256
	let zone = vec CBzoneLength
	InitializeCbStorage(zone, 1, CBzoneLength, 0)
	let cb1 = GetCb(zone)
	let cb2 = GetCb(zone)
	let DA1,DA2 = 0,0
	DA1<<DA.restore = 1
	DA2<<DA.track = restore? T>>P.FirstCyl, lastDiskAddress>>DA.track
	@lastDiskAddress = -1
	@nextDiskCommand = 0// In case there is not microcode - assums that the disk is idle
	if restore then DoDiskCommand(cb1, 0, DA1, 0, 0,msb rshift offset DC.seekOnly )//Restore 
	DoDiskCommand(cb2, 0, DA2, 0, 0,msb rshift offset DC.seekOnly )//do Seek 

	//wait for command issued
	for i = 0 to 32000 do if (cb2>>CB.status & DSTdoneBits) ne 0 then break
	//if diskStatus>>DST.NotLoaded eq 3 then return

	//wait for seek completed
	for i = 0 to 32000 do [ Idle(); if diskStatus>>DST.seekInProgress ne 1 then break ]
	]

and SelectDrive(drive,reset) be
	[ if (drive eq DiskSel) & not reset then return
	DiskSel=drive
	ResetDisk(true)
	]

and DiskStatus() =valof
	[
	@diskStatus = noStat
	Msg(" Diablo-$S Disk status:",nTracks eq 203? "31","44")
	Wait(20)
	if @diskStatus ne noStat then
		[
		Msg(" for Drive #$D:   Last track ",lastDiskAddress>>DA.disk)
		test @lastDiskAddress eq true
			ifso Msg("unknown")
			ifnot Msg("= $D",lastDiskAddress>>DA.track)
		Msg(", Current sector = $D.*n",diskStatus>>DST.sector)
		]
	test (@diskStatus & #367) ne 0 
		ifso Msg("   Status error(s) are:*n      ")
		ifnot Msg("   No errors.*n")
	TypeErrors(@diskStatus,false)
	Msg("*n*n>>")
	resultis @diskStatus
	]

and TypeErrors(status,ComStat; numargs nargs) be
	[
	if nargs ls 2 then ComStat = true
	let sndmsg(txt) be Msg("$S*n      ",txt)
	if status eq noStat then [ sndmsg("No response from Disk Microcode"); return ]

	if status<<DST.CompairErr & ComStat then sndmsg("DiEx Read and Check Error!")
	if status<<DST.seekFailed then sndmsg("Seak Incomplete!")
	test status<<DST.NotLoaded eq 3 
		ifso sndmsg("Heads not loaded")
		ifnot
			[
			if status<<DST.seekInProgress then sndmsg("Seek in Progress")
			if status<<DST.notReady then sndmsg("Drive NOT ready")
			]
	if status<<DST.dataLate then sndmsg("Data Late; Write inhibeted!")
	if ComStat & status<<DST.noTransfer then sndmsg("No Transfer last sector!")
	if status<<DST.checksumError then sndmsg("Checksum Error - read data invalid!")
	if status<<DST.finalStatus eq 1 then sndmsg("Hardware Error or Sector Overflow!")
	if status<<DST.finalStatus eq 2 then sndmsg("Check Err on 'Read and compair'!")
	if status<<DST.finalStatus eq 3 then sndmsg("Disk command with Illegal Sector!")


	]