// =====================================================
// Получение информации о BIOS
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW:    http://www.glasnet.ru/~frolov
//            или
//         http://www.dials.ccas.ru/frolov
// =====================================================
#include <stdio.h>
#include <conio.h>
#include <dos.h>

// Структура области данных с информацией о BIOS
typedef struct _BIOSINFO
{
  int nSize;                   // размер структуры
  unsigned char bModel;        // код модели компьютера
  unsigned char bSubModel;     // дополнительный код модели
  unsigned char bBIOSRevision; // номер изменений версии BIOS
  unsigned char bHardwareCfg;  // конфигурация аппаратуры
  int reserved1;               // зарезервировано
  int reserved2;               // зарезервировано
} BIOSINFO;

int main(void) 
{ 
  union REGS  rg;
  struct SREGS srg;
  int   i;
  BIOSINFO far *lpbi;
  void far* lp;
  unsigned char bHdwCfg;

  printf("\nBIOSINFO (C)A. Frolov, 1997");

  // Конструируем указатель на дату изготовления
  // BIOS. Эта дата записана в ПЗУ по адресу F000h:FFF5h
  _FP_SEG(lp) = 0xf000;
  _FP_OFF(lp) = 0xfff5;

  // Выводим дату на экран
  printf("\n\nBIOS data:        ");
  for(i=0; i<8; i++)
    putch(*((char far *)lp + i));

  // Вызываем функцию C0h для получения адреса
  // таблицы конфигурации компьютера.
  rg.h.ah = 0xc0;
  int86x(0x15, &rg, &rg, &srg);

  // Если в BIOS нет данной функции,
  // читаем код модели компьютера из ПЗУ по адресу F000h:FFFEh.
  if(rg.x.cflag == 1) 
  {
    printf("\nFunction C0h INT 15h not supported\n");
    
    // Конструируем указатель на код модели
    _FP_SEG(lp) = 0xf000;
    _FP_OFF(lp) = 0xfffe;

    // Выводим код модели компьютера на экран
    printf("\nModel:             %02.2X",
      (unsigned char)(*(char far *)lp));
    return(-1);
  }
     
  // Конструируем укзатель на таблицу
  // информации о BIOS
  _FP_SEG(lpbi) = srg.es;
  _FP_OFF(lpbi) = rg.x.bx;

  // Выводим на экран содержимое таблицы
  printf("\nBIOSINFO address: %Fp"
         "\nBIOSINFO Size:    %d"
         "\nModel:            %02.2X"
         "\nSubModel:         %d"
         "\nBIOS Revision:    %d"
         "\nHardvare Cfg:     %02.2X"
         "\nReserved1:        %02.2X"
         "\nReserved2:        %02.2X",
   lpbi, lpbi->nSize, lpbi->bModel, lpbi->bSubModel,
   lpbi->bBIOSRevision, lpbi->bHardwareCfg,
   lpbi->reserved1, lpbi->reserved2);
   
  // Определяем конфигурацию компьютера
  printf("\n\nHardware configuration"
           "\n----------------------");

  // Запоминаем байт конфигурации
  bHdwCfg = lpbi->bHardwareCfg;

  // Расшифровываем байт конфигурации
  if(bHdwCfg & 0x80)
    printf("\nDMA Channel 3");
  
  if(bHdwCfg & 0x40)
    printf("\nSecond IRQ Controller 8259");

  if(bHdwCfg & 0x20)
    printf("\nReal Time Clock");

  if(bHdwCfg & 0x10)
    printf("\nUsed function 4Fh INT 15h");

  if(bHdwCfg & 0x8)
    printf("\nBIOS event wait supported");

  if(bHdwCfg & 0x4)
    printf("\nExtended BIOS data used");

  if(bHdwCfg & 0x2)
    printf("\nMicro Channel Bus");

  if(!(bHdwCfg & 0x2))
    printf("\nISA Bus installed\n");
  
  getch();
  return 0;
}
  
