IOS(7) IOS(7) НАЗВАНИЕ ios - дополнительный сегмент ввода/вывода СИНТАКСИС |#include ОПИСАНИЕ Использование дополнительного сегмента ввода/вывода позволяет осуществить прямой доступ к областям физичес- кой памяти, например к видеопамяти графического конт- роллера, регистрам периферийных устройств или еще к че- му-нибудь на системной шине. Доступ к такому сегменту обеспечивается с помощью дополнительной информации, введенной в структуру user. Драйвер ввода/вывода может записать нужные адреса в структуру и предоставить тем самым пользователю доступ к физической памяти. В структуре user появились следующие дополнительные компоненты: |caddr_t u_iospad; /* Физич. адрес доп. сегмента */ |caddr_t u_iosvad; /* Вирт. адрес доп. сегмента */ |long u_iossiz; /* Размер доп. сегмента */ Значения всех этих компонентов должны быть кратны двум килобайтам (величина NBPC в файле ). ПРИМЕР Продемонстрируем управление графическим контроллером 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 | |#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 является машинно-зависимым средством и на других компьютерах может не работать.