/**
*.Name      disk_cfg
*
*.Title     Определить конфигурацию дисковой подсистемы
*
*.Descr     Функция заполняет структуру, описывающую
*           конфигурацию дисковой подсистемы:
*
*              typedef struct _DISK_CONFIG_ {
*                 int  n_floppy;
*                 int  n_hard;
*                 int  t_floppy1;
*                 int  t_floppy2;
*                 int  t_hard1;
*                 int  t_hard2;
*              } DISK_CONFIG;
*
*.Proto     void disk_cfg(DISK_CONFIG* cfg);
*
*.Params        DISK_CONFIG* cfg - указатель на заполняемую
*                                  структуру
*
*.Return    Ничего
*
*.Sample    discshow.c
**/

#include <stdio.h>
#include <dos.h>
#include "sysp.h"

void disk_cfg(DISK_CONFIG* cfg) {

	char unsigned _far *modptr;
	char unsigned pc_type;
	char cfg_byte;
	int  cfg_word;

	union REGS inregs, outregs;


// Определяем тип компьютера

	modptr = FP_MAKE(0xf000,0xfffe);
	pc_type = *modptr;

// В зависимости от типа компьютера выбираем
// способ определения конфигурации дисковой
// подсистемы

	switch (pc_type) {

		case 0xfc:

// Для IBM AT считываем конфигурацию дисковой
// подсистемы из КМОП-памяти

// Считываем байт конфигурации

			outp(0x70, 0x14);
			cfg_byte = inp(0x71);

// Определяем количество установленных флоппи-дисков

			if((cfg_byte & 1) == 0) {

// Если младший бит байта конфигурации равен 0,
// флоппи-диски не установлены

				cfg->n_floppy  = 0;
				cfg->t_floppy1 = 0;
				cfg->t_floppy2 = 0;

			}
			else {

// Определяем количество установленных
// флоппи-дисков

				cfg->n_floppy = ((cfg_byte >> 6) & 3) + 1;

// Определяем типы флоппи-дисков

				outp(0x70, 0x10);
				cfg_byte = inp(0x71);

				cfg->t_floppy2 = cfg_byte & 0xf;
				cfg->t_floppy1 = (cfg_byte >> 4) & 0xf;

			}

// Определяем конфигурацию жестких дисков

			outp(0x70, 0x12);
			cfg_byte = inp(0x71);

			if(cfg_byte == 0) {

// Если обе тетрады равны нулю, система
// не содержит жестких дисков

				cfg->n_hard  = 0;
				cfg->t_hard1 = 0;
				cfg->t_hard2 = 0;
			}
			else {

// Определяем тип первого диска - диска C:

				if((cfg_byte & 0xf) != 0xf)
					cfg->t_hard1 = cfg_byte & 0xf;

				else {
					outp(0x70, 0x19);
					cfg->t_hard1 = inp(0x71);
				}

// Определяем тип второго диска - диска D:

				if((cfg_byte & 0xf0) != 0xf0)
					cfg->t_hard2 = (cfg_byte >> 4) & 0xf;

				else {
					outp(0x70, 0x1a);
					cfg->t_hard2 = inp(0x71);
				}

			}

// Вычисляем количество установленных
// в системе жестких дисков

			cfg->n_hard = 0;
			if(cfg->t_hard1 != 0) cfg->n_hard++;
			if(cfg->t_hard2 != 0) cfg->n_hard++;

// Для некоторых совместимых с IBM AT машин невозможно
// определить тип диска, так как в КМОП-памяти для
// типа диска установлено значение 0, несмотря на то,
// что диск установлен (например машина Bondwell,
// модель В-300). В таких случаях можно определить
// наличие жесткого диска, используя слово
// конфигурации, возвращаемое прерыванием INT 11h.

			if(cfg->n_hard == 0) {

				int86(0x11, &inregs, &outregs);
				cfg_word = outregs.x.ax;

// Определяем наличие жесткого диска

				if((cfg_word & 1) != 0) {

					cfg->n_hard =  1;

// Считаем, что тип используемого жесткого
// диска неопределен

					cfg->t_hard1 = 0;
					cfg->t_hard2 = 0;

				}
			}

		break;

		default:

// Для остальных типов компьютеров вызываем
// прерывание INT 11h, используем возвращаемый
// этим прерыванием байт конфигурации

			int86(0x11, &inregs, &outregs);
			cfg_word = outregs.x.ax;

// Определяем количество установленных
// флоппи-дисков

			cfg->n_floppy = ((cfg_word >> 6) & 3) + 1;

// Считаем, что тип используемого флоппи-диска
// неопределен

			cfg->t_floppy1 = 0;
			cfg->t_floppy2 = 0;

// Определяем наличие жесткого диска

			if((cfg_word & 1) != 0) {

				cfg->n_hard =  1;

// Считаем, что тип используемого жесткого
// диска неопределен

				cfg->t_hard1 = 0;
				cfg->t_hard2 = 0;

			}

		break;

	}

}
