IOS(7)
НАЗВАНИЕ
ios - дополнительный сегмент ввода/вывода
СИНТАКСИС
#include <sys/user.h>
ОПИСАНИЕ
Использование дополнительного сегмента ввода/вывода
позволяет осуществить прямой доступ к областям физической памяти, например к видеопамяти графического контроллера, регистрам периферийных устройств или еще к чему-нибудь на системной шине. Доступ к такому сегменту
обеспечивается с помощью дополнительной информации,
введенной в структуру user. Драйвер ввода/вывода может
записать нужные адреса в структуру и предоставить тем
самым пользователю доступ к физической памяти.
В структуре user появились следующие дополнительные
компоненты:
caddr_t u_iospad; /* Физич. адрес доп. сегмента */
caddr_t u_iosvad; /* Вирт. адрес доп. сегмента */
long u_iossiz; /* Размер доп. сегмента */
Значения всех этих компонентов должны быть кратны двум
килобайтам (величина NBPC в файле <sys/param.h>).
ПРИМЕР
Продемонстрируем управление графическим контроллером
AGC-1 из прикладной программы. Для этого надо иметь
доступ к памяти контроллера, что и достигается с помощью ios. Память контроллера расположена с адреса
0xfcc00000 и имеет длину 0x240000 (вместе с видеопамятью).
Установка процессом соотвествующих полей структуры user
осуществляется с помощью открытия специального файла
/dev/agc. При этом выполняется функция agcopen драйвера
AGC (ее текст хранится в файле /usr/src/uts/io/agc.c).
Функция устанавливает поля
u.u_iosvad = (caddr_t) 0xfcc00000;
u.u_iospad = (caddr_t) 0xfcc00000;
u.u_iossiz = 0x240000;
Для доступа к любому внутреннему регистру конроллера
AGC-1 используются два регистра, вынесенных на внешнюю
шину: регистр адреса - для указания номера внутреннего
регистра, регистр данных - для указания данных, которые
должны быть занесены во внутренний регистр (или прочитаны из него). Регистры имеют следующие адреса: регистр
адреса - 0xfcc3c000, регистр данных - 0xfcc3c002.
Мы будем изменять два внутренних регистра - регистр высоты экрана и регистр масштабирования. Предполагается,
что на графическом экране уже есть изображение (запустите предварительно какой-либо тест). Тогда, меняя содержимое внутренних регистров, мы сможем изменять изображение.
#include <fcntl.h>
#define HEIGHT 0x008A
#define ZOOM 0x00EA
typedef unsigned short ushort;
main (argc, argv)
int argc;
char *argv[];
{
int i, j, k, fd, old_value;
if ((fd = open ("/dev/agc", 0, O_RDWR)) < 0) {
perror ("\nOpen error /dev/agc :");
exit (0);
}
/* Прочитаем значение высоты экрана в строках */
old_value = read_register (HEIGHT);
/* Будем изменять высоту экрана (сначала уменьшаем до
нуля, а потом увеличиваем до исходного значения */
for (i=old_value; i>=1; i--) {
write_register (HEIGHT, i);
/* задержка */
for (j=0; j<1000; j++) k = j/231;
}
for (i=1; i<=old_value; i++) {
write_register (HEIGHT, i);
for (j=0; j<1000; j++) k = j/231;
}
/* Будем изменять регистр масштабирования */
for (i=0; i<16; i++) {
write_register (ZOOM, (i | (i<<4)) << 8);
sleep (1);
}
for (i=15; i>=0; i--) {
write_register (ZOOM, (i | (i<<4)) << 8);
sleep (1);
}
close (fd);
}
/* Запись в регистр контроллера */
void write_register (number, value)
int number; /* Номер регистра */
int value; /* Значение регистра */
{
ushort *adr= (ushort *) 0xfcc3c000;
ushort *dat= (ushort *) 0xfcc3c002;
ushort val;
*adr = number;
*dat = value;
}
/* Чтение регистра контроллера */
int read_register (number)
int number; /* Номер регистра */
{
ushort *adr= (ushort *) 0xfcc3c000;
ushort *dat= (ushort *) 0xfcc3c002;
*adr = number;
return ((int) *dat);
}
ПРЕДОСТЕРЕЖЕНИЯ
Неосторожное использование ios может нарушить работу
системы.
Ios является машинно-зависимым средством и на других
компьютерах может не работать.