2 | Содержание | 4

Управление вводом-выводом: железо с точки зрения приложений.

Но бывают устройства, о которых система ничего не знает. Тут появляются два варианта работы с ними.

Вариант A. Напрямую из приложений.

Ядро предоставляет API, позволяющие приложениям самостоятельно обрабатывать железо напрямую. Для общения с железом нужно:
  1. иметь возможность доступа к соответствующим портам ввода/вывода;
  и/или

  2. иметь возможность доступа к пространству PCI;
  и/или

  3. иметь возможность доступа к нужной области физической памяти;
  и/или

  4. обрабатывать IRQ от устройства.
    
1. Приложение может попытаться зарезервировать диапазон портов, нужный для общения с устройством (сисфункция 46). Ядро хранит список уже зарезервированных портов (статический массив на 255 входов по адресу RESERVED_PORTS, каждый вход содержит TID владельца, начало и конец зарезервированной области) и не даст зарезервировать диапазон, перекрывающийся с чем-то уже занятым. Если же всё в порядке, то [kernel.asm, rpal2] ядро разрешает в карте разрешения ввода/вывода процессора для запрашивающего потока обращения к запрошенным портам (кстати, при создании потока его карта инициализируется общей разделяемой между всеми потоками, которая запрещена для записи; при попытке первой записи процессор бросает #PF, его обработчик отслеживает эту ситуацию, выделяет новую страницу для карты с разрешённой записью, записывает её в структуру потока и возвращает управление), а также добавляет диапазон в общий список зарезервированных. После этого приложение получает возможность из ring-3 обращаться напрямую к нужным портам. При загрузке ядро резервирует для себя некоторые системные порты. Функция 46 позволяет потоку также освободить ранее выделенные им же порты.

2. Здесь ядро берёт на себя все операции, а приложениям выделяет сисфункцию 62. Которая в принципе может быть запрещена (функция 21.12), но по умолчанию разрешена.

3. Доступ из приложения к любым конкретным адресам в физической памяти безусловно запрещен. К "бортовой" памяти устройств (называемой также блоками ввода-вывода с отображением на память, Memory-Mapped I/O или MMIO) прикладные программы должны обращаться через API-функции и драйверы устройств.

Но что делать с нестандартными устройствами и "бездрайверным железом"? Колибри предоставляет пользовательскому приложению возможность отображения (page mapping) скрытых от него физических адресов MMIO на видимое ему "своё" адресное пространство, используя для этого подфункции 11-13 той же функции 62. Разработчик нового драйвера или инженер-электронщик, тестирующий новое устройство, должен заранее указать его PCI-адрес в системной константе mmio_pci_addr. По умолчанию эта константа в ядре не определена и пользовательский доступ к MMIO закрыт.

4. Для этого есть набор из трёх функций: 42, 44, 45. Когда приходит IRQ, поведение системы зависит от того, какое именно IRQ пришло. - IRQ0, IRQ1, IRQ6, IRQ13, IRQ14, IRQ15 - специальные номера, их ядро обрабатывает самостоятельно (обработка IRQ0=таймера и IRQ1=клавиатуры описана в предыдущем посте, IRQ6 - дискета, IRQ14 и IRQ15 - жёсткие диски)

Oстальные IRQ разбиваются на две категории в зависимости от определения константы USE_COM_IRQ при компиляции ядра: если она ненулевая, то первая состоит из IRQ3 и IRQ4, иначе первая пуста; вторая состоит из всех остальных. IRQ из первой группы может перехватить приложение, IRQ из второй группы может перехватить драйвер (о драйверах - ниже). Перехват приложением заключается в вызове функции 45 для нужного IRQ и определения действий при поступлении IRQ функцией 44. Если IRQ перехвачено, то его обработка заключается в считывании значений из определённых портов (определённых функцией 44) и складывания их в буфер. Приложение в любой момент может прочитать этот буфер функцией 42.

Вариант Б. Из соответствующего драйвера.

Подробно про то, что из себя представляет драйвер, как его можно загрузить и как приложение (и другие драйвера) может с ним общаться, рассказано здесь.

Драйвер выполняется в ring-0 и, как следствие, получает доступ ко всему, чему можно. В частности, с чтением/записью в порты никаких проблем не возникает. Кроме того, ядро предоставляет некоторые сервисы драйверам. В их числе:
2 | Содержание | 4

Pterox' DocPack R6. Last Edition: 29.05.2010. История выпусков