[comp.sys.ibm.pc] AT&T PC6300 CMOS Clock program: source

jxh@cup.portal.com (Jim - Hickstein) (12/29/88)

Here is the much-requested source for my stupid little program that reads
the CMOS clock chip in an AT&T PC6300 and feeds the date and time to DOS.
I use it at boot time, since IBM PC-DOS 3.30 doesn't have the AT&T-modified
IO system (any 86-DOS old-timers out there?) that "knows" what to do when the
DATE and TIME commands are issued, i.e. call the Olivetti BIOS to touch the
clock chip directly.  I have a big binder full of 7th-generation photocopies of
the BIOS listing from an Olivetti M24 (what a 6300 is, really), and managed to
glean the following kernels of trivia therefrom.  Note that it was written to
compile under Logitech Modula-2 release 2, but the gist of it is certainly
portable to whatever environment you happen to be suffering from at the moment.
Voila!
------
MODULE ATTClock;

(* Insofar as I wrote this while an employee of Telcom General Corporation,
   it is Copyright 1986 Telcom General Corporation, but they're defunct,
   so draw your own conclusions. 

AT&T PC 6300 BIOS Interrupt Service Routine

INT 1A

Read Time:

ENTRY	(AH) = FE (-2) 
EXIT	(BX) = days since 1984-Jan-01 (1=1984-Jan-01)
	(CH) = hour
	(CL) = minute
	(DH) = second
	(DL) = hundredth

MS-DOS Set Date/Time Function(s)

INT 21H
 al=0 OK, AL=FF invalid
Set Date 2B cx year  dh mo1-12 dl day 1-31
Set Time 2D ch hour, cl minute, dh seconds, dl hundredths
Get Date 2A cx year  dh mo1-12 dl day 1-31 al wkdy 0N-6S
Get Time 2C ch hour, cl minute, dh seconds, dl hundredths

*)

FROM SYSTEM IMPORT GETREG, SETREG, SWI, AX, BX, CX, DX;

FROM InOut IMPORT Write, WriteCard, WriteString, WriteLn;

TYPE
  Months = (Nul, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);

VAR
  year, date, hour, minute, second, hundredth,
  daysThisYear: CARDINAL;
  MonthLength: ARRAY Months OF CARDINAL;
  MonthNames: ARRAY [0..3*13] OF CHAR;
  month: Months;

PROCEDURE Initialize;

  VAR
    m: Months;

  BEGIN
    year := 1984;
    MonthNames := '***JanFebMarAprMayJunJulAugSepOctNovDec ';
    FOR m := Jan TO Dec DO MonthLength[m] := 31 END;
    MonthLength[Feb] := 28;
    MonthLength[Apr] := 30;
    MonthLength[Jun] := 30;
    MonthLength[Sep] := 30;
    MonthLength[Nov] := 30;
  END Initialize;


PROCEDURE SetDate;

  VAR
    tmp, tmp2: CARDINAL;

  BEGIN
    tmp := ORD(month)*256 + date;
    SETREG(AX, 2B00H) (* Set Date *);
    SETREG(CX, year);
    SETREG(DX, tmp);
    SWI(21H);
    tmp := hour*256 + minute;
    tmp2 := second*256 + hundredth;
    SETREG(AX, 2D00H) (* Set time *);
    SETREG(CX, tmp);
    SETREG(DX, tmp2);
    SWI(21H);
  END SetDate;


PROCEDURE DisplayDate;

  PROCEDURE Write2Digits(num: CARDINAL);

    BEGIN
      IF num < 10 THEN Write('0') END;
      WriteCard(num, 1)
    END Write2Digits;

  VAR
    i, j: CARDINAL;

  BEGIN
    WriteCard(date, 1); Write('-');
    i := ORD(month) * 3;
    FOR j := i TO i+2 DO Write(MonthNames[j]) END; Write('-');
    WriteCard(year, 1); Write(' ');
    Write2Digits(hour); Write(':');
    Write2Digits(minute); Write(':');
    Write2Digits(second); Write('.');
    Write2Digits(hundredth); WriteLn
  END DisplayDate;

PROCEDURE GetTimeFromATT;

  VAR
   bx, cx, dx: CARDINAL;

  BEGIN
    SETREG(AX, 0FE00H);
    SWI(1AH);
    GETREG(BX, bx);
    GETREG(CX, cx);
    GETREG(DX, dx);
    date := bx;
    hour := cx DIV 256;
    minute := cx MOD 256;
    second := dx DIV 256;
    hundredth := dx MOD 256
  END GetTimeFromATT;

BEGIN
  Initialize;
  GetTimeFromATT;
  LOOP
    IF (((year MOD 4) = 0) AND
        (((year MOD 100) # 0) OR ((year MOD 400) = 0))) THEN
      daysThisYear := 366;
      MonthLength[Feb] := 29
    ELSE
      daysThisYear := 365;
      MonthLength[Feb] := 28
    END;
    IF date >= daysThisYear THEN
      DEC(date, daysThisYear);
      INC(year)
    ELSE
      EXIT
    END
  END;
  month := Jan;
  WHILE MonthLength[month] <= date DO
    DEC(date, MonthLength[month]);
    INC(month);
  END;
  INC(date) (* first date is 1, not 0 *);
  SetDate;
  DisplayDate
END ATTClock.
------
Jim Hickstein
jxh@cup.portal.com
...!sun!portal!cup.portal.com!jxh