Вход на хостинг
IT-новости
20.04.2016 iPhone 2017 года поместят в водонепроницаемый корпус из стекла
Линейка iPhone в новом году серьезно поменяется. В этом уверен аналитический исследователь Мин Чи Ку......
30.07.2015 Ищем уникальный контент для сайта
Ищем уникальный контент для сайта Без уникального контента Ваш сайт обречен на то, что его страницы......
__asm__("lcall (%%esi); cld "
"jc 1f "
"xor %%ah, %%ah "
"1:"
: "=c" (*value),
"=a" (result)
: "1" (PCIBIOS_READ_CONFIG_DWORD),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect)); // точка входа в сервис
break;
}
return (int)((result & 0xff00) >> 8);
}
Помимо средств BIOS32 для работы с конфигурационным пространством устройства PCI в защищенном режиме также используется Configuration Mechanism #1. Его порядок работы был рассмотрен в «Configuration Mechanism #1»: в порт CONFIG_ADDRESS (0xCF8) заносится адрес, соответствующий формату, приведенному на рис. 2; обращением к порту CONFIG_DATA (0xCFC) производится чтение или запись данных в требуемый регистр конфигурационного пространства.
Формировать адрес установленного формата будет макрос PCI_CONF1_ADDRESS():
#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
Самый старший бит установлен в 1 – это позволит нам получить данные из порта CONFIG_DATA.
После того как адрес сформирован, записываем его в порт CONFIG_ADDRESS.
Функция pci_direct_read() выполняет обращение к устройству PCI при помощи Configuration Mechanism #1:
static int pci_direct_read(int bus, int dev, int fn, int reg, int len, u32 *value)
{
Параметры функции – номер шины bus, номер устройства на шине dev, номер функции fn, смещение в конфигурационном пространстве reg, длина запрашиваемых данных (байт/слово/двойное слово). Результат помещается в параметр value, который передается по ссылке.
Проверяем правильность переданных параметров:
if (bus > 255 || dev > 31 || fn > 7 || reg > 255)
return -EINVAL;
Формируем адрес при помощи макроса PCI_CONF1_ ADDRESS() и записываем его в порт CONFIG_ADDRESS:
outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
Считываем значение из порта CONFIG_DATA:
switch (len) {
case 1: // считываем байт
*value = inb(0xCFC + (reg & 3));
break;