[Back to HARDWARE SWAG index] [Back to Main SWAG index] [Original]

    {
    ¯ Does anyone know how to get the hard drive type(s) from CMOS ?
    ¯ I can't seem to find this information documented anywhere.

    This is probably a lot more than you are asking for but. . .
    NOTE: one function (Long2Str) is not defined in this because it comes from
    a commercial unit.  Basically all it does is convert a number to a string
    and return the string.
         This code comes from a unit I wrote to get all kinds of niffty
    information about your system.  I think I included everything you will need
    to get it up and running.  If you get any strange problems or ones you
    can't seem to resolve, let me know and I'll see if I can pass you the right
    information.
    }

    Uses
      KMath,
      Dos;

    type
      String80 = String[80];  { some general purpose string types }
      String40 = String[40];
      String30 = String[30];
      String20 = String[20];
      String12 = String[12];
      String10 = String[10];
      String5  = String[5];

      CMOSRec = Record
        Found     : Boolean;  { was a CMOS found to exist }
        CmosDate  : String30; { the date found in CMOS }
        CmosTime  : String30; { the time found in CMOS }
        VideoType : String10; { Type of video found in CMOS }
        Coproc    : Boolean;  { does CMOS report a math coprocessor }
        FloppyA   : String12; { type of floppy drive for A }
        FloppyB   : String12; { Type of floppy drive for B }
        Hard0     : Byte;     { Type of hard drive for drive 0 }
        Hard1     : Byte;     { Type of hard drive for Drive 1 }
        ConvenRam : Word;     { amount of conventional ram indicated }
        ExtendRam : Word;     { amount of extended Ram indicated }
        checkSum  : Boolean;  { Did checksum pass }
      end; { CMOS Rec }

    const
      { values of constants for CMOS }
      DayName: array[0..7] of string[9] = ('Sunday', 'Monday', 'Tuesday',
                                           'Wednesday', 'Thursday', 'Friday',
                                           'Saturday', 'Sunday');
      MonthName: array[0..12] of string[9] = ('???', 'January', 'February', 'March',
                                              'April', 'May', 'June', 'July',
                                              'August', 'September', 'October',
                                              'November', 'December');
      ScreenName: array[0..3] of string[10] = ('EGA/VGA', 'CGA 40col',
                                               'CGA 80col', 'Monochrome');
      FloppyName: array[0..5] of string[11] = ('none', '5.25" 360K',
                                               '5.25" 1.2M', '3.5"  720K',
                                               '3.5"  1.44M', '3.5"  2.88M');
      CMOSport : Byte = $70; { port to access the CMOS }

    {===========================================================================}

    VAR
      Regs : Registers; { General purpose variable to access registers }
      CMOS : CMOSRec;   { variable to hold CMOS data }

    function nocarry : boolean;
    { returns the status of the carry flag }
    begin
      nocarry:=regs.flags and fcarry = $0000
    end; {nocarry}

    {---------------------------------------------------------------------------}

    Function ByteToWord(ByteA, ByteB : byte) : word;
    begin
       ByteToWord := Word(ByteB) shl 8 + ByteA
    end; {cbw}

    {---------------------------------------------------------------------------}

    Function BitIsSet(CheckWord : Word; AndValue : Word) : Boolean;
    { returns true if the bit(s) indicated in AndValue are set in CheckByte }
    BEGIN
      BitIsSet := CheckWord AND AndValue = AndValue;
    end;

    {---------------------------------------------------------------------------}

    Function ReadCMOS(addr: byte): byte;
    { read a value from the CMOS }
    Begin
      if CMOSport = $70 then
      begin
        inline($FA);
        Port[CMOSport] := addr;
        readCMOS := Port[CMOSport + 1];
        inline($FB)
      end
    end; {readCMOS}

    {---------------------------------------------------------------------------}

    function addzero(b: byte): string5;
    var
      c2: string[2];
    begin
      Str(b:0, c2);
      if b < 10 then
        c2:='0' + c2;
      addzero:=c2
    end; {addzero}

    {---------------------------------------------------------------------------}

    Function ChangeBCD(b: byte): byte;
    { change a BCD into a byte structure }
    Begin
      ChangeBCD:=(b and $0F) + ((b shr 4) * 10)
    end; {ChangeBCD}

    {---------------------------------------------------------------------------}

    Function GetCMOSDate : String30;
    { gets the date found in the CMOS and returns it in string format }
    VAR
      Date,
      Century,
      Year,
      Month : Byte;
      WorkStr : String30;
    BEGIN
      WorkStr := '';
      date    := ChangeBCD(readCMOS(7));
      century := ChangeBCD(readCMOS($32));
      year    := ChangeBCD(readCMOS(9));
      month   := ChangeBCD(readCMOS(8));
      WorkStr := DayName[readCMOS(6)]+', ';
      {case country.DateFormat of
        0, 3..255 :}
          WorkStr := WorkStr + Monthname[month]+' '+IntToStr(date)+', '+IntToStr(century)+addzero(year);
     {   1 :
          WorkStr := WorkStr + Long2Str(date)+', '+Monthname[month]+' '+Long2Str(century)+addzero(Year);
        2 :
          WorkStr := WorkStr + Long2Str(century)+addzero(Year)+', '+Monthname[month]+' '+Long2Str(date);
      end; {case}
      GetCMosDate := workStr;
    end; { GetCMOSDate }

    {---------------------------------------------------------------------------}

    Function GetCmosTime : String30;
    { returns the time as found in the CMOS }
    VAR
      CH : Char;
      Hour,
      Min,
      Sec  : Byte;
      WorkStr : String30;
      IsPM    : Boolean;
    BEGIN
      workStr := '';
      hour := ChangeBCD(readCMOS(4));
      min := ChangeBCD(readCMOS(2));
      sec := ChangeBCD(readCMOS(0));
      IsPm := false;
      case hour of
            0: hour := 12;
            1..11: hour := hour;
            12: IsPM := true;
            13..23: begin
                      IsPM := true;
                      hour := hour - 12
                    end;
      end; {case}
      WorkStr := WorkStr + AddZero(hour)+':'+addzero(min)+':'+addzero(sec);
      if IsPM then
        workStr := WorkStr + ' PM'
      Else
        WorkStr := WorkStr + ' AM';
      GetCMOSTime := WorkStr;
    end; { GetCmosTime }

    {---------------------------------------------------------------------------}

    Function GetCmosCheckSum : Boolean;
    { performs checksum on CMOS and returns true if ok }
    VAR
      CheckSum1,
      CheckSum2 : word;
      Count     : Byte;
    BEGIN
      checksum1 := 0;
      for count := $10 to $2D do
        Inc(checksum1, readCMOS(count));
      checksum2 := (word(256) * readCMOS($2E)) + readCMOS($2F);
      if checksum1 = checksum2 then
        GetCmosCheckSum := true
      else
        GetCmosCheckSum := false;
    end; { GetCmosCheckSum }

    {---------------------------------------------------------------------------}

    Procedure GetCMos;
    { gets the cmos record if it exist }
    VAR
      Floppy : Byte;
    BEGIN
      FillChar(CMOS, SizeOf(CMos), 0);
      regs.AH:=$C0;
      Intr($15, regs);
      if nocarry or (Mem[$F000:$FFFE] <= $FC) then
      With CMOS DO
      begin
        Found := true;
        CMOSDate := GetCMOSDate;
        CMOSTime := GetCmosTime;
        VideoType := ScreenName[(readCMOS($14) shr 4) and 3];
        CoProc := BitIsSet(readCMOS($14), 2);
        Floppy := readCMOS($10);
        if (Floppy shr 4) < 5 then
          FloppyA := FloppyName[floppy shr 4]
        else
          FloppyA := 'Unknown '+ Byte2Hex(floppy shr 4);
        if (floppy and $0F) < 5 then
          FloppyB := FloppyName[floppy and $0F]
        else
          FloppyB := 'Unknown '+ Byte2Hex(floppy and $0F);

        Hard0 := readCMOS($12);
        Hard0 := Hard0 shr 4;
        Hard1 := ReadCmos($12);
        Hard1 := Hard1 and $0F;
        if Hard0 = $F then
          Hard0 := readCMOS($19)
        Else Hard0 := $FF; { error }
        if Hard1 = $F then
          Hard1 := readCMOS($1A)
        Else Hard1 := $FF;
        ConvenRam := word(256) * readCMOS($16) + readCMOS($15); { value in K }
        ExtendRam := word(256) * readCMOS($18) + readCMOS($17); { value in K }
        CheckSum := GetCmosCheckSum;
      end
      else
        CMOS.Found := false;
    end;

    begin
      GetCmos;
      Writeln(CMOS.Found);
      Writeln(CMOS.CmosDate);
      Writeln(CMOS.CmosTime);
      Writeln(CMOS.VideoType);
      Writeln(CMOS.Coproc);
      Writeln(CMOS.FloppyA);
      Writeln(CMOS.FloppyB);
      Writeln(CMOS.Hard0);
      Writeln(CMOS.Hard1);
      Writeln(CMOS.ConvenRam);
      Writeln(CMOS.ExtendRam);
      Writeln(CMOS.checkSum);
    end.

[Back to HARDWARE SWAG index] [Back to Main SWAG index] [Original]