Чтение онлайн

ЖАНРЫ

Шины PCI, USB и FireWire

Гук Михаил Юрьевич

Шрифт:

Для 16-битного интерфейса реального режима, V86 и 16-битного защищенного режима, функции PCI BIOS вызываются через прерывание Int lAh; номер функции задается при вызове в регистре AX. Возможна и программная имитация прерывания дальним вызовом по физическому адресу 000FFE6Eh (стандартная точка входа в обработчик Int lAh) с предварительным занесением в стек регистра флагов.

 

Для 32-разрядных вызовов защищенного режима все эти же функции вызываются через точку входа, найденную через каталог 32-разрядных сервисов (см. ниже), при этом назначение входных и выходных регистров и флага CF сохраняется. До использования 32-разрядного интерфейса следует сначала найти его каталог и убедиться в наличии сервисов PCI BIOS по идентификатору «$PCI» (049435024h).

Вызовы

требуют глубокого стека (до 1024 байт). Признаком нормального выполнения является CF = 0 и AH = 0; при CF = 1 AH содержит код ошибки:

• 81h – неподдерживаемая функция;

• 83h – неправильный идентификатор производителя;

• 86h – устройство не найдено;

• 87h – неправильный номер регистра PCI;

• 88h – установка не удалась;

• 89h – слишком маленький буфер для данных.

Функции PCI BIOS перечислены ниже:

AX = B101h – проверка присутствия PCI BIOS. При наличии PCI BIOS возвращает CF = 0, AH = 0 и EDX = 20494350h (строка символов «PCI»); проверяться должны все три признака. При этом в AL находится описатель аппаратного механизма доступа к конфигурационному пространству и генерации специальных циклов PCI:

• бит 0 – поддержка механизма № 1 для доступа к конфигурационному пространству;

• бит 1 – поддержка механизма № 2 для доступа к конфигурационному пространству;

• биты [2:3] = 00 (резерв);

• бит 4 – поддержка генерации специального цикла с использованием механизма № 1;

• бит 5 – поддержка генерации специального цикла с использованием механизма № 2;

• биты [6:7] = 00 (резерв).

В регистрах BH и BL возвращается старший и младший номер версии (BCD-цифры), в CL – максимальный номер шины PCI, присутствующий в системе (число шин – 1, поскольку они нумеруются с нуля последовательно). В регистре EDI может возвращаться линейный адрес точки входа 32-разрядных сервисов BIOS. Этот адрес возвращается не всеми версиями BIOS (некоторые не изменяют EDI); для проверки можно при вызове обнулять EDI и проверять на нуль возвращенное значение.

• AX = B102h – поиск устройства по идентификатору. При вызове в CX указывается идентификатор устройства, в DX – идентификатор производителя, в SI – индекс (порядковый номер) устройства. При успешном возврате в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции. Для нахождения всех устройств с указанными идентификаторами вызовы выполняют, последовательно инкрементируя SI от 0 до получения кода возврата 86h.

• AX = B103h – поиск устройства по коду класса. При вызове в ECX[23:16] указывается код класса, в ECX[15:8] – подкласса, в ECX[7:0] – интерфейс, в SI – индекс устройства (аналогично предыдущему). При успешном возврате в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции.

• AX = B106h – генерация специального цикла PCI. При вызове в BL указывается номер шины, в EDX – данные специального цикла.

• AX = B108h – чтение байта из конфигурационного пространства устройства PCI. При вызове в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции, в DI – номер регистра (0–FFh). При успешном возврате в CL – считанный байт.

• AX = B109h – чтение слова из конфигурационного пространства устройства PCI.

При вызове в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции, в DI – номер регистра (0–FFh, четный). При успешном возврате в CX – считанное слово.

• AX = B10Ah – чтение двойного слова из конфигурационного пространства устройства PCI. При вызове в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции, в DI – номер регистра (0–FFh, кратный 4). При успешном возврате в ECX – считанное двойное слово.

• AX = B10Bh – запись байта в конфигурационное пространство устройства PCI.

При вызове в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции, в DI – номер регистра (0–FFh), в CL – записываемый байт.

• AX = B1 °Ch – запись слова в конфигурационное

пространство устройства PCI.

При вызове в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0] – номер функции, в DI – номер регистра (0–FFh, четный), в CX – записываемое слово.

• AX = B10Dh – запись двойного слова в конфигурационное пространство устройства PCI. При вызове в BH – номер шины, в BL[7:3] – номер устройства, BL[2:0]—номер функции, в DI – номер регистра (0–FFh, кратный 4), в ECX – записываемое двойное слово.

• AX = B10Eh – определение возможностей назначения прерываний (GET_IRQ_ROUTING_OPTIONS). При вызове BX=0, ES: EDI указывает на структуру параметров буфера для результата, состоящую из слова с длиной буфера, за которым располагается дальний указатель на его начало. DS в 16$разрядом режиме указывает на сегмент с физическим адресом F0000, в 32$разрядном определяется правилами из следующего раздела. При успешном возврате в BX находится битовая карта запросов IRQx, в которой единичное значение бита означает, что данный вход контроллера прерываний используется исключительно шиной PCI.

В буфер помещается последовательный набор структур, описывающих возможности и назначение прерываний для каждого устройства PCI (табл. 5.2). При возврате в структуре параметров буфера возвращается его реальная длина; если при вызове указан буфер, не вмещающий весь результат, устанавливается код ошибки 89h.

• AX = B10Fh – назначение линий запроса прерываний (SET_PCI_IRQ). При вызове в BH задается номер шины, в BL – номер устройства (биты [7:3]) и функции (биты [2:0]), для которой назначается запрос; в CL указывается вывод (0Ah – INTA#,… 0Dh – INTD#), в CH – желаемый номер IRQx (0…0Fh, причем 0 соответствует отключению INTx# от входов контроллера). Значение DS аналогично предыдущей функции. Если заказанное назначение невозможно, при возврате устанавливается код ошибки 88h. При использовании данной функции следует выполнять и сопутствующие изменения в конфигурационных регистров всех затрагиваемых устройств и их функций (см. главу 3).

Поиск 32-разрядных сервисов BIOS

32-разрядные сервисы BIOS32 ищутся через каталог 32-разрядных сервисов.[14] Адрес точки входа в каталог сервисов заранее не известен, но известен способ его нахождения: в диапазоне адресов памяти 0E0000-0FFFFFh в началах параграфов (младшие 4 бита адреса нулевые) ищется строка-сигнатура «32» заголовка (число 325F5F33h), за которой следует 32-разрядный физический адрес точки входа в каталог. Точки входа в сами сервисы ищутся через каталог сервисов. Номер, параметры вызываемых функций и результаты передаются на регистрах процессора.

Для поиска сервиса в каталоге 4-байтная строка-идентификатор сервиса заносятся в регистр EAX, в EBX заносится 0 (код функции поиска в каталоге) и выполняется дальний вызов (CALL FAR) по адресу точки входа в каталог. Результат поиска передается на регистрах: AL = 00h – сервис найден, при этом в EBX – базовый Смотри документ «Standard BIOS 32-bit Service Directory*. адрес сервиса, в ECX – его длина (определяет длину сегмента), EDX – смещение точки входа от начала сервиса (от EBX). Если AL = 81h – сервис не найден.

До попытки использования каталога сервисов следует убедиться в корректности заголовка, проверив его контрольную сумму: накопленная сумма всех байтов заголовка должна быть нулевой. Длина заголовка (в параграфах) указана в байте со смещением 9, в байте 8 – номер ревизии заголовка. Проверка контрольной суммы обязательна, поскольку 4-байтная сигнатура может совпасть с фрагментом программного кода BIOS (строка 32 дизассемблируется как POP DI; XOR SI,[BP + SI]). 32-разрядные сервисы вызываются дальними вызовами (CALL FAR), при этом сегмент кода CS должен иметь базу в начале 4-килобайтной страницы, в которую попадает точка входа, а лимит должен позволять охватывать эту и следующую страницу.[15] Сегмент DS должен иметь такую же базу и не меньший лимит. Напомним, что здесь идет речь о физических адресах (после страничного преобразования линейных).

Поделиться с друзьями: