{ SAGE II/IV Configuration Control Unit

  File:	    CONFIGSAGE.TEXT
  Date:	    19-Sep-83
  Version:  2A


  COPYRIGHT (c) 1983 SAGE Computer Technology


  Development History:

  1    23-Mar-83  Initial release.
  2	5-Aug-83  Added DEVINFO field for CP/M.	 Relaxed device and
		  subdevice number restriction in Conf_Assign.
		  Put in BIOS compatibility check.
		  Added variables and extra space in Winchester
		  configuration.
  2A   19-Sep-83  Changed device number checks on Floppy, Winchester
		  and Extra Serial ports.
		  Allow use with BIOS version 2.4 & 3.3.
		   


  Description:

  This unit provides record formats and routines which may be used for
  configuring the SAGE II/IV BIOS.  These routines read and write the
  raw information which is stored in the BIOS.	Also provided are
  routines for converting certain raw data items to a more appropriate
  user format.

}

UNIT Config_Sage;

INTERFACE

TYPE

  Conf_Rates =	  (Conf_RSync,Conf_X1,Conf_X16,Conf_X64);
  Conf_DataBits = (Conf_5Data,Conf_6Data,Conf_7Data,Conf_8Data);
  Conf_StopBits = (Conf_Invalid,Conf_1Stop,Conf_1_5Stop,Conf_2Stop);
  Conf_PrtMode =  (Conf_None,Conf_Serial,Conf_ParInterrupt,Conf_ParPoll);
  
  Conf_Type =	  (Conf_CvBaud,Conf_CvStepRate);
  
  { Terminal Configuration }
  Conf_Terminal = PACKED RECORD
		    BaudRate:INTEGER;
		    BreakAllowed:BOOLEAN;
		    XonXoffFlag:BOOLEAN;
		    Reserve1:0..63;
		    RateFactor:Conf_Rates;
		    DataBits:Conf_DataBits;
		    ParityEnabled:BOOLEAN;
		    ParityEven:BOOLEAN;
		    StopBits:Conf_StopBits;
		  END;
  
  { Remote Serial Channel Configuration }
  
  Conf_Remote = PACKED RECORD
		  BaudRate:INTEGER;
		  XONin:BOOLEAN;
		  XONout:BOOLEAN;
		  Reserve1:0..63;
		  RateFactor:Conf_Rates;
		  DataBits:Conf_DataBits;
		  ParityEnabled:BOOLEAN;
		  ParityEven:BOOLEAN;
		  StopBits:Conf_StopBits;
		  PollDelay:INTEGER;
		  Reserve2:0..255;
		  DSR_Polling:BOOLEAN;
		  Reserve3:0..127;
		END;
  
  { Printer Channel Configuration }
  
  Conf_Printer = PACKED RECORD
		   Timeout:INTEGER;
		   PollTime:INTEGER;
		   NoLF:BOOLEAN;
		   Reserve1:0..127;
		   Mode:Conf_PrtMode;
		   Reserve2:0..63;
		 END;
  
  { Floppy Configuration }
  
  Conf_Floppy = PACKED RECORD
		  Cylinders:0..255;
		  Sides:0..255;
		  Gap3:0..255;
		  SectorsPerTrack:0..255;
		  DataLength:0..255;
		  Skew:0..255;
		  BytesPerSector:INTEGER;
		  MotorOnDelay:INTEGER;
		  NoDMAflag:BOOLEAN;
		  HeadLoad:0..127;
		  HeadUnload:0..15;
		  StepRate:0..15;
		  IBMflag:BOOLEAN;
		  NCIflag:BOOLEAN;
		  RAWflag:BOOLEAN;
		  Reserve1:0..31;
		  Reserve2:0..63;
		  MFMflag:BOOLEAN;
		  Reserve3:0..1;
		  IgnoreErrors:BOOLEAN;
		  Reserve4:0..127;
		  Tries:0..255;
		  DoubleStep:BOOLEAN;
		  Reserve5:0..127;
		  SoftErrors:0..255;
		  Gap3Format:0..255;
		  PatternFormat:0..255;
		  LastError:0..255;
		  FirstError:0..255;
		  Reserve6:ARRAY[0..4] OF INTEGER;
		END;

  { RAM Disk Configuration }
  
  Conf_RamDisk = PACKED RECORD
		   BaseHigh:INTEGER;
		   BaseLow:INTEGER;
		   TopHigh:INTEGER;
		   TopLow:INTEGER;
		   Reserve1:0..255;
		   BootRamDisk:BOOLEAN;
		   Reserve2:0..127;
		 END;
  
  { System Configuration }

  Conf_System = PACKED RECORD
		  Seconds:0..255;
		  Days:0..255;
		END;

  Conf_OpSystem = ARRAY[0..15] OF INTEGER;
  
  Conf_ChanTable = ARRAY[0..31] OF PACKED RECORD
				     Channel:0..255;
				     SubChannel:0..255;
				   END;
  
  Conf_Winch = PACKED RECORD
		 Cylinders:INTEGER;
		 BytesPerSector:INTEGER;
		 StepTime:INTEGER;
		 SlewTime:INTEGER;
		 StepCtr:INTEGER;
		 HeadSettleTime:INTEGER;
		 PreCompTrack:INTEGER;
		 SpecialType:INTEGER;
		 Tests:INTEGER;
		 ShipTrack:INTEGER;
		 HeaderCount:INTEGER;
		 LowReadCounter:INTEGER;
		 HighReadCounter:INTEGER;
		 SectorsPerTrack:0..255;
		 Heads:0..255;
		 Tries:0..255;
		 SelectBit:0..255;
		 LastError:0..255;
		 FirstError:0..255;
		 SoftErrors:0..255;
		 LastHardError:0..255;
		 SeekUnderflow:INTEGER;
		 CRC:INTEGER;
		 SyncBit:INTEGER;
		 ExtraHeadSettle:INTEGER;
		 WriteTries:0..255;
		 RawTries:0..255;
		 Reserved:ARRAY[1..8] OF INTEGER;
	       END;

  Conf_DevInfo = ARRAY[1..16] OF INTEGER;
  
  Conf_WDevInfo = ARRAY[0..3,0..15] OF INTEGER;
  
  Conf_File = PACKED RECORD
		Header:ARRAY[0..12] OF INTEGER;
		Name:PACKED ARRAY[0..3] OF CHAR;
		BiosSize:INTEGER;
		BiosBuffers:INTEGER;
		BisoStart:INTEGER;
		BiosVersion:0..255;
		BIOSSubVersion:0..255;
		Floppy0:Conf_Floppy;
		Floppy1:Conf_Floppy;
		Terminal:Conf_Terminal;
		Remote:Conf_Remote;
		RamDisk:Conf_RamDisk;
		Printer:Conf_Printer;
		TimeAdj:Conf_System;
		OpSystem:Conf_OpSystem;
		ChanTable:Conf_ChanTable;
		DevInfo:Conf_DevInfo;
		XSerial1:Conf_Remote;
		XSerial2:Conf_Remote;
		XSerial3:Conf_Remote;
		XSerial4:Conf_Remote;
		Winch1:Conf_Winch;
		Winch2:Conf_Winch;
		Winch3:Conf_Winch;
		Winch4:Conf_Winch;
		WinDevInfo:Conf_WDevInfo;
		DummyBlock:ARRAY[0..255] OF INTEGER;
	      END;

PROCEDURE Conf_RD_Terminal(VAR Data:Conf_Terminal);
PROCEDURE Conf_Wt_Terminal(Data:Conf_Terminal);

PROCEDURE Conf_RD_Remote(VAR Data:Conf_Remote);
PROCEDURE Conf_Wt_Remote(Data:Conf_Remote);

PROCEDURE Conf_RD_Printer(VAR Data:Conf_Printer);
PROCEDURE Conf_WT_Printer(Data:Conf_Printer);

PROCEDURE Conf_RD_Floppy(Drive:INTEGER; VAR Data:Conf_Floppy);
PROCEDURE Conf_WT_Floppy(Drive:INTEGER; Data:Conf_Floppy);

PROCEDURE Conf_RD_RamDisk(VAR Data:Conf_RamDisk);
PROCEDURE Conf_WT_RamDisk(Data:Conf_RamDisk);

PROCEDURE Conf_RD_System(VAR Data:Conf_System);
PROCEDURE Conf_WT_System(Data:Conf_System);

PROCEDURE Conf_RD_OpSystem(VAR Data:Conf_OpSystem);
PROCEDURE Conf_WT_OpSystem(Data:Conf_OpSystem);

PROCEDURE Conf_RD_ChanTable(VAR Data:Conf_ChanTable);
PROCEDURE Conf_WT_ChanTable(Data:Conf_ChanTable);

PROCEDURE Conf_RD_XSerial(Device:INTEGER; VAR Data:Conf_Remote);
PROCEDURE Conf_WT_XSerial(Device:INTEGER; VAR Data:Conf_Remote);

PROCEDURE Conf_RD_Winch(Drive:INTEGER; VAR Data:Conf_Winch);
PROCEDURE Conf_WT_Winch(Drive:INTEGER; Data:Conf_Winch);

PROCEDURE Conf_RD_DevInfo(VAR Data:Conf_DevInfo);
PROCEDURE Conf_WT_DevInfo(Data:Conf_DevInfo);

PROCEDURE Conf_RD_WDevInfo(VAR Data:Conf_WDevInfo);
PROCEDURE Conf_WT_WDevInfo(Data:Conf_WDevInfo);


{ Converts raw data to user familiar form }
FUNCTION Conf_Rd_Conversion(Device:INTEGER; DataType:Conf_Type;
			    Data:INTEGER):INTEGER;

{ Converts user familiar form to raw data }
FUNCTION Conf_Wt_Conversion(Device:INTEGER; DataType:Conf_Type;
			    Data:INTEGER):INTEGER;

{ Change Device Map Assignments }
PROCEDURE Conf_Assign(Channel,Device,SubUnit:INTEGER);

{ Restore Device Map Assignments }
PROCEDURE Conf_Restore;

{ Test for SAGE IV }
FUNCTION Conf_SGIV:BOOLEAN;



IMPLEMENTATION

VAR
  StartChanTable:Conf_ChanTable;
  Multi:BOOLEAN;


FUNCTION LogToPhys(Device:INTEGER):INTEGER;
VAR
  TempMap:Conf_ChanTable;
BEGIN
  LogToPhys:=0;
  IF (Device >= 0) AND (Device < 32) THEN
    BEGIN
      Conf_Rd_ChanTable(TempMap);
      LogToPhys:=TempMap[Device].Channel;
    END;
END;

PROCEDURE Conf_RD_Terminal{(VAR Data:Conf_Terminal)};
BEGIN
  UNITREAD(128,Data,0,0,1);
END;

PROCEDURE Conf_Wt_Terminal{(Data:Conf_Terminal)};
BEGIN
  UNITWRITE(128,Data,0,0,1);
END;


PROCEDURE Conf_RD_Remote{(VAR Data:Conf_Remote)};
BEGIN
  UNITREAD(128,Data,0,0,7);
END;

PROCEDURE Conf_Wt_Remote{(Data:Conf_Remote)};
BEGIN
  UNITWRITE(128,Data,0,0,7);
END;


PROCEDURE Conf_RD_Printer{(VAR Data:Conf_Printer)};
BEGIN
  UNITREAD(128,Data,0,0,6);
END;

PROCEDURE Conf_WT_Printer{(Data:Conf_Printer)};
BEGIN
  UNITWRITE(128,Data,0,0,6);
END;


PROCEDURE Conf_RD_Floppy{(Drive:INTEGER; VAR Data:Conf_Floppy)};
BEGIN
  IF LogToPhys(Drive) IN [4,5] THEN
    UNITREAD(128,Data,0,0,Drive);
END;

PROCEDURE Conf_WT_Floppy{(Drive:INTEGER; Data:Conf_Floppy)};
BEGIN
  IF LogToPhys(Drive) IN [4,5] THEN
    UNITWRITE(128,Data,0,0,Drive);
END;


PROCEDURE Conf_RD_RamDisk{(VAR Data:Conf_RamDisk)};
BEGIN
  UNITREAD(128,Data,0,0,11);
END;

PROCEDURE Conf_WT_RamDisk{(Data:Conf_RamDisk)};
BEGIN
  UNITWRITE(128,Data,0,0,11);
END;


PROCEDURE Conf_RD_System{(VAR Data:Conf_System)};
BEGIN
  UNITREAD(128,Data,0,0,0);
END;

PROCEDURE Conf_WT_System{(Data:Conf_System)};
BEGIN
  UNITWRITE(128,Data,0,0,0);
END;

PROCEDURE Conf_RD_OpSystem{(VAR Data:Conf_OpSystem)};
BEGIN
 UNITREAD(128,Data,0,2,0);
END;

PROCEDURE Conf_WT_OpSystem{(Data:Conf_OpSystem)};
BEGIN
  UNITWRITE(128,Data,0,2,0);
END;

PROCEDURE Conf_RD_ChanTable{(VAR Data:Conf_ChanTable)};
BEGIN
  UNITREAD(128,Data,0,1,0);
END;

PROCEDURE Conf_WT_ChanTable{(Data:Conf_ChanTable)};
BEGIN
  UNITWRITE(128,Data,0,1,0);
END;

PROCEDURE Conf_RD_XSerial{(Device:INTEGER; VAR Data:Conf_Remote)};
VAR
  Addr:INTEGER;
BEGIN
  Addr:=LogToPhys(Device);
  IF (Multi AND ((Addr>=13) AND (Addr<=20))) OR ((NOT Multi) AND
      ((Addr>=13) AND (Addr<=16))) THEN
    UNITREAD(128,Data,0,0,Device);
END;

PROCEDURE Conf_WT_XSerial{(Device:INTEGER; VAR Data:Conf_Remote)};
VAR
  Addr:INTEGER;
BEGIN
  Addr:=LogToPhys(Device);
  IF (Multi AND ((Addr>=13) AND (Addr<=20))) OR ((NOT Multi) AND
      ((Addr>=13) AND (Addr<=16))) THEN
    UNITWRITE(128,Data,0,0,Device);
END;

PROCEDURE Conf_RD_Winch{(Drive:INTEGER; VAR Data:Conf_Winch)};
BEGIN
  IF LogToPhys(Drive) = 9 THEN
    UNITREAD(128,Data,0,0,Drive);
END;

PROCEDURE Conf_WT_Winch{(Drive:INTEGER; Data:Conf_Winch)};
BEGIN
  IF LogToPhys(Drive) = 9 THEN
    UNITWRITE(128,Data,0,0,Drive);
END;

PROCEDURE Conf_RD_DevInfo {(VAR Data:Conf_DevInfo)};
BEGIN
  UNITREAD(128,Data,0,5,0);
END;

PROCEDURE Conf_WT_DevInfo {(Data:Conf_DevInfo)};
BEGIN
  UNITWRITE(128,Data,0,5,0);
END;


PROCEDURE Conf_RD_WDevInfo {(VAR Data:Conf_WDevInfo)};
BEGIN
  UNITREAD(128,Data,0,6,0);
END;

PROCEDURE Conf_WT_WDevInfo {(Data:Conf_WDevInfo)};
BEGIN
  UNITWRITE(128,Data,0,6,0);
END;

FUNCTION Conf_RD_Conversion{(Device:INTEGER; DataType:Conf_Type;
			     Data:INTEGER):INTEGER};
BEGIN
  CASE DataType OF
    Conf_CvBaud:BEGIN
		  IF Device IN [1,2,7,8] THEN
		    BEGIN
		      IF Data <= 0 THEN
			BEGIN
			  IF Device IN [1,2] THEN Conf_RD_Conversion:=0
			  ELSE
			    Conf_RD_Conversion:=9600;
			END
		      ELSE
		      IF Data = 19 THEN Conf_RD_Conversion:=2000
		      ELSE
		      IF Data = 21 THEN Conf_RD_Conversion:=1800
		      ELSE
		      IF Data = 350 THEN Conf_RD_Conversion:=110
		      ELSE
		      IF Data = 512 THEN Conf_RD_Conversion:=75
		      ELSE
		      IF Data = 769 THEN Conf_RD_Conversion:=50
		      ELSE
			Conf_Rd_Conversion:=(19200 DIV Data)*2;
		    END
		  ELSE
		    IF Data = 0 THEN Conf_RD_Conversion:=9600
		    ELSE
		      CASE ORD(ODD(Data) AND ODD(15)) OF
			0:Conf_RD_Conversion:=50;
			1:Conf_RD_Conversion:=75;
			2:Conf_RD_Conversion:=110;
			4:Conf_RD_Conversion:=150;
			5:Conf_RD_Conversion:=300;
			6:Conf_RD_Conversion:=600;
			7:Conf_RD_Conversion:=1200;
			8:Conf_RD_Conversion:=1800;
			9:Conf_RD_Conversion:=2000;
		       10:Conf_RD_Conversion:=2400;
		       12:Conf_RD_Conversion:=4800;
		       14:Conf_RD_Conversion:=9600;
		       15:Conf_RD_Conversion:=19200;
		     END;
		END;
    Conf_CvStepRate:BEGIN
		      Conf_Rd_Conversion:=32-(Data*2);
		    END;
  END;
END;

FUNCTION Conf_WT_Conversion{(Device:INTEGER; DataType:Conf_Type;
			     Data:INTEGER):INTEGER};
BEGIN
  CASE DataType OF
    Conf_CvBaud:BEGIN
		  IF Device IN [1,2,7,8] THEN
		    BEGIN
		      IF Data <= 0 THEN Conf_WT_Conversion:=0
		      ELSE
			IF Data = 2000 THEN Conf_WT_Conversion:=19
			ELSE
			IF Data = 1800 THEN Conf_WT_Conversion:=21
			ELSE
			IF Data = 110 THEN Conf_WT_Conversion:=350
			ELSE
			IF Data = 50 THEN Conf_WT_Conversion:=769
			ELSE
			  Conf_Wt_Conversion:=(19200 DIV Data)*2;
		    END
		  ELSE
		    BEGIN
		      IF Data = 50 THEN Conf_WT_Conversion:=48
		      ELSE
		      IF Data = 75 THEN Conf_WT_Conversion:=49
		      ELSE
		      IF Data = 110 THEN Conf_WT_Conversion:=50
		      ELSE
		      IF Data = 150 THEN Conf_WT_Conversion:=52
		      ELSE
		      IF Data = 300 THEN Conf_WT_Conversion:=53
		      ELSE
		      IF Data = 600 THEN Conf_WT_Conversion:=54
		      ELSE
		      IF Data = 1200 THEN Conf_WT_Conversion:=55
		      ELSE
		      IF Data = 1800 THEN Conf_WT_Conversion:=56
		      ELSE
		      IF Data = 2000 THEN Conf_WT_Conversion:=57
		      ELSE
		      IF Data = 2400 THEN Conf_WT_Conversion:=58
		      ELSE
		      IF Data = 4800 THEN Conf_WT_Conversion:=60
		      ELSE
		      IF Data = 9600 THEN Conf_WT_Conversion:=62
		      ELSE
		      IF Data = 19200 THEN Conf_WT_Conversion:=63
		      ELSE
			Conf_WT_Conversion:=62; {Default to 9600}
		    END;
		END;
    Conf_CvStepRate:BEGIN
		      IF Data > 32 THEN Data:=32
		      ELSE
			IF Data <= 0 THEN Data:=1;
		      Conf_Wt_Conversion:=16-((Data+1) DIV 2);
		    END;
  END;
END;

PROCEDURE Conf_Assign{ (Channel,Device,SubUnit:INTEGER) };
VAR
  NewChanTable:Conf_ChanTable;
BEGIN
  IF (Channel >= 0) AND (Channel < 32) AND (Device >= 0) AND (Device < 256)
     AND (SubUnit >= 0) AND (SubUnit < 256) THEN
     BEGIN
       Conf_RD_ChanTable(NewChanTable);
       NewChanTable[Channel].Channel:=Device;
       NewChanTable[Channel].SubChannel:=SubUnit;
       Conf_WT_ChanTable(NewChanTable);
     END;
END;

PROCEDURE Conf_Restore;
BEGIN
  Conf_WT_ChanTable(StartChanTable);
END;

FUNCTION Conf_SGIV;
VAR
  Result:INTEGER;
BEGIN
  UNITREAD(128,Result,0,3,0);
  Conf_SGIV:= Result <> 0;
END;

PROCEDURE Init;
VAR
  Version:INTEGER;
BEGIN
  Version:=0;
  UNITREAD(128,Version,0,4,0);
  IF (Version <> 770) AND (Version <> 515) AND (Version <> 771) AND 
     (Version <> 1026) THEN
    BEGIN
      WRITELN('CONFIGSAGE must use BIOS 2.4 or MU 3.3');
      WRITELN;
      HALT;
    END;
  Multi:=(ORD(ODD(Version) AND ODD(255))) = 3;
END;

BEGIN { Initialization }
  Conf_RD_ChanTable(StartChanTable);
  Init;
END.

                                                     