home *** CD-ROM | disk | FTP | other *** search
- UNIT CMOSStuf;
-
- {--------------------}
- INTERFACE
- {--------------------}
-
- TYPE { Public types }
- CMOSMemRec = RECORD
- ClockRegs : ARRAY[1..14] OF BYTE;
- Diagnostic : BYTE;
- ShutdownStatus : BYTE;
- FloppyDriveType : BYTE;
- Reserved1 : BYTE;
- FixedDriveType : BYTE;
- Reserved2 : BYTE;
- EquipmentType : BYTE;
- BaseMemory : INTEGER;
- ExtendedMemory1 : INTEGER;
- Reserved3 : ARRAY[1..21] OF BYTE;
- CheckSum : INTEGER;
- ExtendedMemory2 : INTEGER;
- CenturyDate : BYTE;
- InfoFlag : BYTE;
- Reserved4 : ARRAY[1..12] OF BYTE
- END; { Record }
-
- CONST { Public constants }
- CMOSNoError = 0;
- CMOSNotAtError = 1;
- CMOSCheckSumError = 2;
-
- FUNCTION CMOSError : WORD; { Returns result of CMOS operation }
- FUNCTION CMOSIsAnAT : BOOLEAN; { Detects if a PC/AT computer }
- PROCEDURE GetCMOSMem(VAR C : CMOSMemRec); { Read CMOS registers }
- PROCEDURE SetCMOSMem(C : CMOSMemRec); { Write to CMOS registers }
-
-
- {--------------------}
- IMPLEMENTATION
- {--------------------}
-
- CONST { Private constants }
- CMOSMemorySize = 64;
-
- VAR { Private variables }
- CMOSErr : WORD;
-
- {--------------------}
-
- FUNCTION CMOSError : WORD;
-
- BEGIN
- CMOSError := CMOSErr;
- CMOSErr := 0
- END; { CMOSError }
-
-
- {--------------------}
-
- FUNCTION CMOSIsAnAT : BOOLEAN;
-
- CONST
- ATSignature = $FC;
- CMOSMachIDSeg = $F000;
- CMOSMachIDOfs = $FFFE;
-
- BEGIN
- CMOSIsAnAT := (MEM[CMOSMachIDSeg : CMOSMachIDOfs] = ATSignature)
- END; { CMOSIsAnAT }
-
-
- {--------------------}
-
- PROCEDURE ComputeCMOSCheckSum(VAR C : CMOSMemRec);
-
- VAR
- i : INTEGER;
-
- BEGIN
- WITH C DO
- { Calculate the sum of the designated bytes }
- BEGIN
- CheckSum := FloppyDriveType + Reserved1 + FixedDriveType
- + Reserved2 + EquipmentType
- + LO(BaseMemory) + HI(BaseMemory)
- + LO(ExtendedMemory1) + HI(ExtendedMemory1);
-
- FOR i := 1 TO 21 DO
- CheckSum := CheckSum + Reserved3[i];
-
- { Checksum isn't a true integer, so swap hi and lo bytes }
- CheckSum := SWAP(CheckSum)
- END
- END; { ComputeCMOSCheckSum }
-
-
- {--------------------}
-
- FUNCTION ReadCMOSPort(PortNum : BYTE) : BYTE;
-
- CONST
- CMOSLatch = $70;
- CMOSIOPort = $71;
-
- BEGIN
- PORT[CMOSLatch] := PortNum;
- ReadCMOSPort := PORT[CMOSIOPort]
- END; { ReadCMOSPort }
-
-
- {--------------------}
-
- PROCEDURE WriteCMOSPort(PortNum : BYTE; { Register address within port }
- Data : BYTE); { Data to be written }
-
- CONST
- CMOSLatch = $70;
- CMOSIOPort = $71;
-
- BEGIN
- PORT[CMOSLatch] := PortNum;
- PORT[CMOSIOPort] := Data
- END; { WriteCMOSPort }
-
-
- {--------------------}
-
- PROCEDURE GetCMOSMem(VAR C : CMOSMemRec);
-
- VAR
- i : INTEGER;
- VarSeg : WORD;
- VarOfs : WORD;
-
- BEGIN
- IF CMOSIsAnAT
- THEN BEGIN
- VarSeg := Seg(C); { Find location of C }
- VarOfs := Ofs(C);
- FOR i := 0 TO CMOSMemorySize - 1 DO { Read record into C }
- MEM[VarSeg : VarOfs + i] := ReadCMOSPort(i);
- CMOSErr := CMOSNoError
- END
- ELSE CMOSErr := CMOSNotATError
- END; { GetCMOSMem }
-
-
- {--------------------}
-
- PROCEDURE SetCMOSMem(C : CMOSMemRec);
-
- VAR
- i : INTEGER;
- VarSeg : WORD;
- VarOfs : WORD;
- TestRec : CMOSMemRec;
-
- BEGIN
- IF CMOSIsAnAT
- THEN BEGIN
- ComputeCMOSCheckSum(C); { Calculate new checksum }
- VarSeg := Seg(C); { Find location of C }
- VarOfs := Ofs(C);
- FOR i := 0 TO CMOSMemorySize - 1 DO { Move record into CMOS }
- WriteCMOSPort(i, MEM[VarSeg : VarOfs + i]);
- GetCMOSMem(TestRec); { Read record back, }
- ComputeCMOSCheckSum(TestRec); { and compare checksums }
- IF (TestRec.CheckSum = C.CheckSum)
- THEN CMOSErr := CMOSNoError
- ELSE CMOSErr := CMOSCheckSumError
- END
- ELSE CMOSErr := CMOSNotATError
- END; { SetCMOSMem }
-
-
- {====================}
- { INITIALIZATION }
- {====================}
-
- BEGIN
- CMOSErr := CMOSNoError { Initialize error variable }
- END.
-