Программирование драйверов Windows

       

Регистры устройств


Драйверы взаимодействуют с подключаемыми устройствами путем чтения из регистров или записи в их внутренние регистры. Каждый внутренний регистр устройства обычно реализует одну из функций, перечисленных ниже:

  • Регистр состояния. Обычно считывается драйвером, когда тому необходимо получить информацию о текущем состоянии устройства.
  • Регистр команд. Биты этого регистра управляют устройством некоторым образом, например, начиная или прекращая передачу данных. Драйвер обычно производит запись в такие регистры.
  • Регистры данных. Обычно такие регистры используются для передачи данных между устройством и драйвером. В выходные (output) peгucmpы, регистры вывода, драйвер производит запись, в то время как информация входных (input) регистров, регистров ввода, считывается драйвером.
  • Доступ к регистрам устройства достигается в результате выполнения инструкций доступа к портам ввода/вывода (port address) или обращения к определенным адресам в адресном пространстве оперативной памяти (memory-mapped address), что и интерпретируются системой как доступ к аппаратным регистрам.

    Простые устройства (такие, как стандартный интерфейс параллельного порта, см. таблицу 5.1 — не путать с регистрами устройств, которые могут подключаться извне к параллельному порту!) имеют небольшое число ассоциированных регистров. В то же время, сложное аппаратное обеспечение (например, графические адаптеры) может иметь значительно больше регистров. Число и назначение регистров определяется разработчиками аппаратного обеспечения и должно быть полно и однозначно описано в документации. Однако зачастую такая однозначность так и остается недостижимой мечтой, а разработчику драйвера приходится определять реальное

    назначение нужных битов в устройствах используя случайно добытый тестовый программный пример неизвестного автора или метод собственных проб и собственных ошибок. Более того, часто выясняется, что биты, объявленные в документации как "зарезервированные" (reserved), вовсе не являются тем безобидным предметом, о котором не следует и беспокоиться.


    Таблица 5.1. Регистры интерфейса стандартного параллельного порта (SPP)



    Смещение Доступ Регистр Описание
    0 Read/Write Data (DR) Байт данных, передаваемый через параллельный порт
    1 Read only Биты 0-1

    Бит 2

    Бит 3

    Бит 4

    Бит 5

    Бит 6

    Бит 7
    Status (SR)

    PIRQ

    ERROR#

    SELECT

    OUT_OF_PAPER ACK#

    BUSY#
    Текущее состояние порта

    Зарезервированы

    0 — прерывание было запрошено портом (т.е. если сигнал ACK# вызвал прерывание)

    0 — произошла ошибка

    1 — принтер выбран (включен)

    1 — в принтере отсутствует бумага

    отображает состояния линии Ack#

    0 — принтер занят (1 - разрешение на вывод очередного байта)
    2 Read/Write

    Бит 0

    Бит 1

    Бит 2

    Бит 3

    Бит 4

    Биты 5-7
    Control (CR)

    STROBE#

    AUTO_LF

    INIT#

    SELECT_IN#

    ENABLE_INT
    Команды, посылаемые в порт

    1 — строб передачи данных в/из порта

    1 — автоматическая подача строки

    0 — инициализировать принтер

    1 — выбрать принтер

    1 — разрешает прерывания по спаду сигнала на линии ACK#

    зарезервированы
    Коварность отдельных устройств проявляется еще и в том (например, в случае с адаптерами EGA и VGA), что смысл ассоциированного регистра во второй операции доступа к нему определяется значением данных, отправленных в этот регистр во время первой операции доступа. Пусть у нас имеется X &#8212 указатель на регистр в "терминах" адресов памяти, и сначала мы сделали *X=1 и после этого получили n=*X &#8212 число конных матросов на лекции А.Блока. Но если мы сделали *X=2, то можем получить n=*X &#8212 температуру, при которой следует готовить сапоги всмятку, то есть совершенно другие по смыслу значения.


    Содержание раздела