Листинг 7-7. EMMEXIST.C
------------------------------------------------------------------
#include
#include
#include
#include
#include "emmconst"
#define DOS_INT 0x21 /*диспетчер функций DOS*/
#define DOS_IOCTL 0x44 /*функция IOCTL DOS*/
#define IOCTL_GETINFO 0x00 /*подфункция "Получить информа-
цию об устройстве" IOCTL*/
#define IOCTL_OUTSTAT 0x07 /*подфункция "Получить состояние
вывода" IOCTL*/
#define READY_OUTPUT 0xFF /*устройство готово к выводу*/
#define IS_DEVICE 0x0080 /*обработчик принадлежит устрой-
ству*/
static char device_name[9] = EMM_DEVICE;
/*
Контролируется наличие расширенной памяти с помощью метода
"открытого обработчика". Устанавливает emm_present в '1',
если расширенная память присутствует, в '0' - если нет.
Функция возвращает '0', если тест наличия завершился успеш-
но. В противном случае возвращается код ошибки DOS вызова
функции DOS, которая не выполнилась во время теста наличия
расширенной памяти.
*/
emm_exists(emm_present)
int *emm_present; /*указатель на индикатор наличия
менеджера расширенной памяти*/
{
int return_code; /*код возврата операции с файлом*/
int handle; /*обработчик файлов*/
unsigned int dev_attr; /*атрибуты драйвера устройства*/
unsigned int dev_status; /*выходное состояние устройства*/
if (_dos_open(device_name, O_RDONLY, &handle)) {
/*не удалось открыть файл*/
if (errno == ENOENT) { /*файл не существует*/
return_code = 0; /*мы ожидали, что это могло
случиться*/
*emm_present = 0; /*менеджер расширенной памяти
определенно отсутствует*/
} else
return_code = errno; /*тест наличия завершился
безуспешно*/
} else
if (!(return_code = ioctl_getattr(handle, &dev_attr))) {
/*получен атрибут*/
if (!(return_code = ioctl_outstat(handle, &dev_status)))
/*получено выходное состояние*/
/*менеджер расширенной памяти присутству-
ет, если обработчик принадлежит устрой-
ству и готов к выводу*/
*emm_present = ((dev_status == READY_OUTPUT) && (dev_attr
& IS_DEVICE)) ? 1 : 0;
close(handle); /*закрывается обработчик файла*/
}
return(return_code);
}
/*
Получается слово атрибутов DOS для открытого обpаботчика,
связанного с открытым файлом или устройством. Возвращает 0,
если функция завершилась успешно, в противном случае воз-
вращает код ошибки DOS
*/
ioctl_getattr(handle, attrib)
int handle; /*открытый обpаботчик файла/устройства*/
unsigned int *attrib; /* -> возвращенная информация об устройстве*/
{
int rc;
union REGS regs;
regs.h.ah = DOS_IOCTL; /*управление вводом/выводом DOS для
устройств*/
regs.h.al = IOCTL_GETINFO; /*получить информацию об устройс-
тве*/
regs.x.bx = handle;
int86(DOS_INT, ®s, ®s); /*вызов функции DOS*/
if (!regs.x.cflag) { /*если не произошло ошибки*/
*attrib = regs.x.dx; /*возвращаются атрибуты
файла/устройства*/
rc = 0; /*функция выполнилась успешно*/
} else
rc = regs.x.ax; /*возвращается код ошибки*/
return(rc);
}
/*
Получает выходное состояние файла или устройства. Возвра-
щенное состояние 0 означает, что устройство неготово для
вывода; состояние 0xFF00 означает, что устройство готово
для вывода. Возвращается 0, если функция завершилась ус-
пешно. В противном случае возвращается код ошибки DOS.
*/
ioctl_outstat(handle, status)
int handle; /*открытый обpаботчик файла/устройства*/
unsigned int *status; /* -> слово состояния вывода*/
{
int rc;
union REGS regs;
regs.h.ah = DOS_IOCTL; /*управление вводом/выводом DOS для
устройств*/
regs.h.al = IOCTL_OUTSTAT; /*получить состояние вывода*/
regs.x.bx = handle;
int86(DOS_INT, ®s, ®s); /*вызов функции DOS*/
if (!regs.x.cflag) { /*если не произошло ошибки*/
*status = regs.h.al; /*возвращается состояние
вывода*/
rc = 0; /*функция выполнилась успешно*/
} else
rc = regs.x.ax; /*возвращается код ошибки*/
return(rc);
}
/*
Проверяет наличие pасшиpенной памяти с помощью метода
"получить вектор". Устанавливает emm_present в '1', если
расширенная память присутствует, '0' - если нет. Данная
функция всегда возвращает '0'.
*/
emm_exists2(emm_present)
int *emm_present;
{
int len;
char far *device_name; /*указатель на имя символьного
устройства*/
char *np;
unsigned int get_int_seg();
FP_SEG(dev_name) = get_int_seg(EMM_INT); /*сегмент драйвера
устройства менеджеpа pасшиpенной памяти*/
FP_OFF(dev_name) = 10; /*смещение имени драйвера символь-
ного устройства*/
/*увидеть, находится ли имя менеджеpа pасшиpенной памяти
по смещению 10 в сегменте EMM_INT*/
for (len = 8, np = device_name; len && *dev_name++ == *np++;
len--);
*emm_present = (len) ? 0 : 1; /*если все символы совпа-
ли менеджеp pасшиpенной памяти присутствует*/
return(0); /*всегда завершается успешно*/
}
/*
Возвращает адрес сегмента вектора прерываний "intno"
*/
unsigned int get_int_seg(intno)
int intno;
{
union REGS regs;
struct SREGS segregs;
regs.h.al = (unsigned char) intno;
regs.h.ah = 0x35; /*функция "Получить вектор" DOS*/
intdosx(®s, ®s, &segregs);
return((unsigned) segregs.es);
}
-------------------------------------------------------------------
|