Определение потребностей PCI устройства в области памяти и ввода-вывода.
Каждое устройство PCI по стандарту имеет 64 байтовую область - т.н. конфигурационное пространство. Которое содержит, как информацию об устройстве, так и т.н. BAR'ы - Base Address Register - регистры, куда записываются адреса выделенные ОС для работы устройства с памятью и вводом-выводом.
В интернете перерыл уже много информации, где говорится, что размер требуемой для устройства памяти можно получить, опросив устройство и записав в BAR единички, а потом прочитать и проанализировать значения из области BAR.
Но непонятны три момента...
Первый - в конфигурационном пространстве PCI устройства содержится 6 регистров BAR. В какой из них производить запись? В первый или во все?
Второй - Регистры (BAR) могут содержать информацию как о потребности PCI устройства в области памяти, так и в области ввода вывода. Как различить такие регистры?
Ну и третий, самый важный вопрос - каким образом анализировать прочитанное из BAR'ов значение?
XROMBAR? Что за зверь? В конфигурационном пространстве есть штука под названием Expansion ROM BAR, но что делает не понятно.
А книжечку поищу. Надеюсь в онлайне есть, т.к. уж очень влом бумажную покупать.
BIOS. Дизассемблирование, модификация, программирование - она?
Спасибо! Весьма интересная книжка! Уже читаю!
Во все, по очреди. Только учти бывают и 64 битные регистры. Два объединяются в один.
0-2 биты определяют тип регистра.
Устройство занулит нужные биты.
Bass address registers - BAR
Bass address (базовый адрес)-это адрес регистров устройства. Обычно эти регистры отображаются на физические адреса памяти. Под устройства PCI зарезервированы адреса 4ГБайта (С0000000-FFFFFFFF), это не строгий диапазон и он может варьироваться Или более устаревшая модель в адресатное пространство портов ввода/вывода. Это и есть основные регистры PCI устройства. Через них происходит программирование, но информация эта зависит от производителя.
Более детально о Bass address.
Если все биты 32 установлены в 0, то Bass address не записан в ячейку.
Если бит 0 установлен в 1, то Bass address задает базовый адрес в пространстве портов I/O.
Иначе если бит 0 установлен в 0, то Bass address задает базовый адрес в пространстве адресов памяти.
Если наш Bass address задает базовый адрес в пространстве портов I/O. То он имеет следующий формат.
|31 2|1|0|
+------------------------------------------------+-+-+
| Bass address |0|1|
+------------------------------------------------+-+-+
32 бита.
Нулевой бит указывает на то, что это пространство портов I/O.
Первый бит зарезервирован.
Остальные указывают адрес базового порта ввода вывода. В старших 16 биттах может находиться муссор.
Если наш Bass address задает базовый адрес в пространстве памяти. То он имеет следующий формат.
| 4|3|2|1|0|
+--------------------------------------------+-+-+-+-+
| Bass address | | |0|
+--------------------------------------------+-+-+-+-+
Либо 32 бита, либо 64 бита.
Нулевой бит указывает на то, что это пространство памяти.
Следующие два бита 1 и 2 определяют тип записи.
0-32 битная запись любой адрес
1-32 битная запись, но адрес меньше мегабайта.
2-64 битная запись любой адрес
3-зарезервировано
Бит 3 – Prefetchable – предпочтения выставляется в один если не вызывает побочных явления при чтении. Если у нас отображаются регистры в память. Так называемые Memory Mapped I/O то при чтении могут срабатывать триггеры, которые могут влиять на работу устройства. Поэтому для регистров этот бит всегда опущен (not prefetchable). А вот для линейного буфера видео карты этот бит может быть выставлен (Prefetchable).
Остальные биты базовый адрес.
Если вы хотите узнать размер памяти, которая отображается в адресное пространство. Или число портов ввода вывода. То вы должны выставить максимальное значение FFFFFFFF и прочитав его. Устройство обнулит биты, которые соответствуют его диапазону адресов. Замечу, что выставляемый адрес должен быть кратным размеру его диапазона, выровнен по этому размеру, поэтому и происходит обнуление битов.
Interrupt Line – если значение не равно 0, то это номер IRQ, который устанавливает BIOS, вовремя выполнения POST на работу устройства это не влияет.
Interrupt Pin - если значение не равно 0, то это номер контакта, который используется для прерывания
1 соответствует INTA#
2 соответствует INTB#
3 соответствует INTC#
4 соответствует INTD#
Остальные значения зарезервированы.
Всякое PCI устройство может иметь свой встроенный BIOS.
Которая располагается по Expansion ROM Base Address. Стандартный диапазон для всех БИОСов PCI устройств у PC-AT совместных компьютеров 0C0000h-0DFFFFh.
Expansion ROM Base Address – Имеет следующий формат
|31 11|10 1|0|
+--------------------------------+-----------------+-+
|Expansion ROMBase Address | резерв |1|
+--------------------------------+-----------------+-+
Нулевой бит Expansion ROM Enable это бит, который отвечает - будет ли задействован БИОС или нет.
Expansion ROMBase Address – старшие 21 бит адреса БИОСа. Если вы попробуете записать значение 0FFFFFFFEh тогда мы получим в ответ размер БИОСа. После нужно восстановить адрес, предварительно схоронив его.
Если вернулись все 0, то БИОСа не существует. Если смотреть от младших битов к старшим, то там идут нули первый единичный бит сигнализирует размер БИОСа. Пример
|11111111 11111111 00000|000 0000000|X|
Размер 64Кб его проще всего вычислить по формуле
addr:=Register and $FFFFF800; Зануляеи служебные биты.
Size:=-Addr; Или команда ассемблера NEG
Размер БИОСа может колебаться в приделах от 64КБ до 16МБ. А его адрес должен быть кратен размеру БИОСа.
Для видео карты БИОС должен располагаться по адресу 0C0000h поэтому в
Expansion ROMBase Address у нее может быть 0.
Ну и сооответственно таким же образом проходися по всему диапазону BAR регистров...
Я правильно понял или нет?
А сколько устройство использует BAR регистров? Все или может только некоторые?
Эт я к чему... Как отличить неиспользуемый BAR от I/O BAR? Тот который отвечает за ввод вывод будет иметь первые биты 01, а тот который не используется 11?
2) Да.
Усли у BAR все 32 бита нули то он не используется.
Если BAR 31-1 биты в ноль и 0 бит в 1 то это Порты ввода вывода. Но адресс порта особенный или неиспользуется. Под словом особенной понимается определенный спецификацией железа или даже можно сказать дефолтовый.
Аналогично и для памяти если служебные биты выставленны, а адресс нуливой то он либы неиспользуется либо дефолтовый.
На шине PCI обнаружилось 4 устройства. 1 полностью соответствует PCI спецификации, три других, изготовленные одним производителем довольно странно себя ведут.
Начнем с того, что после обнаружения устройств, я опрашиваю их конфигурационное пространство. У первого устройства, все BAR'ы изначально девственно чисты и содержат нолики.
В трех остальных устройствах в BARах уже забиты адреса - адрес области памяти и адрес I/O. Адреса ввода вывода разные, области памяти - одинаковые.
Ну, думаю сначала - не беда. Просто мусор.
Пишу регистры единичками, а потом читаю. Первое устройство без проблем выставляет BAR'ы показывая, что хочет 128 кб памяти.
Три других устройства... Выдают те же значения регистров, что и были до записи единичками... Похоже, что эти регистры у устройств вообще не записываемые.
Что я по этому поводу думаю... Конечно, в принципе те три устройства с выставленными адресами могут работать, но при этом получается, что операционка будет не в курсе, что эти адреса уже зарезервированы и при запросе может легко выдать перекрывающийся с этими адресами диапазон для другого устройства!
В общем что это? Сделанные через Ж абоненты PCI или стандарт все же предусматривает жесткую привязку абонентов к адресам?
Лучше возьми последний стандарт на PCI (у меня 3.0) в нем лучше описанно.
Хотя скорее всего у тебя тот случий когда сделали все стандарта.
Что касается PCI-Express то intel добавило расширенное конфигурационное пространство которое теперь находиться в памяти компьютера. Дальше надо в документацию лезть вроде стандарта нет.
ну на пример IDE подключён к PCI?
Мост ISA представляет из себя совокупность устарелых устройств. Раньше они были отдельными микрасхемами. Это PIC, DMA i8237, таймер PIT i8253, RTC\CMOS. К этому мосту подкючен Super IO. В нем нходиться все то что не вошло в северный и южный мосты это PS/2 контроллер, LPT,COM, FDC, IrDA.
Тут еще надо сказать про IO APIC. Он подключен к PCI, но формально находиться в мосте ISA(LPC) так как линии прерываний сходяься только там.
Насамом деле там целая паутина проводов.
Как видно схема такая половина устройств находиться на PCI другая половина на ISA. А шина ISA подключена к PCI.
Да к PCI.
Снял я лог работы с PCI абонентом:
PCI device found!
Device ID: 0x1001191E
Device bus number: 0
Device number: 0
Device function number: 0
---------------- Entering config space ---------------------
Register offset 0x00: 0x1001191E
Register offset 0x04: 0x00000542
Register offset 0x08: 0xFF000004
Register offset 0x0C: 0x00000000
Register offset 0x10: 0x00000000
Register offset 0x14: 0x00000000
Register offset 0x18: 0x00000000
Register offset 0x1C: 0x00000000
Register offset 0x20: 0x00000000
Register offset 0x24: 0x00000000
Register offset 0x28: 0x00000000
Register offset 0x2C: 0x00000000
Register offset 0x30: 0x00000000
Register offset 0x34: 0x00000000
Register offset 0x38: 0x00000000
Register offset 0x3C: 0x00000000
---------------- Writing BAR 0 ---------------------
0xFFFFFFFF
---------------- Reading BAR 0 ---------------------
Register offset 0x10: 0xFFE00000
BAR Type: 0
BAR resourse needs: 2097152 bytes
---------------- Writing BAR 1 ---------------------
0xFFFFFFFF
---------------- Reading BAR 1 ---------------------
Register offset 0x14: 0x00000000
BAR Type: -1
BAR resourse needs: 0 bytes
---------------- Writing BAR 2 ---------------------
0xFFFFFFFF
---------------- Reading BAR 2 ---------------------
Register offset 0x18: 0x00000000
BAR Type: -1
BAR resourse needs: 0 bytes
---------------- Writing BAR 3 ---------------------
0xFFFFFFFF
---------------- Reading BAR 3 ---------------------
Register offset 0x1C: 0x00000000
BAR Type: -1
BAR resourse needs: 0 bytes
---------------- Writing BAR 4 ---------------------
0xFFFFFFFF
---------------- Reading BAR 4 ---------------------
Register offset 0x20: 0x00000000
BAR Type: -1
BAR resourse needs: 0 bytes
---------------- Writing BAR 5 ---------------------
0xFFFFFFFF
---------------- Reading BAR 5 ---------------------
Register offset 0x24: 0x00000000
BAR Type: -1
BAR resourse needs: 0 bytes
Вот первый BAR возвращает значение 0xFFE00000
Что про этот регистр можно сказать?
Это регистр отвечающий за пространство памяти.
Это 32х разрядный регистр.
С нулевым битом Prefetchable;
Далее идут обнуленные разряды адреса.
В бинарном виде регистр выглядит так:
В адресном диапазоне обнулены 17 бит.
Теперь вопрос собственно как действовать дальше?
С одной стороны, если обнулены разряды используемые в диапазоне адресации, то с помощью 17 бит можно адресовать 2^17 байт памяти, что будет равнятся 131 072 байтам памяти.
Но в книге "BIOS дизассемблирование, модификация программирование", рекомендованой в начале темы, описана другая процедура.
Там говорится, что нужно "очистить" служебные биты, инвертировать 32 разряда регистра и прибавить единицу. Якобы полученное значение и будет цифрой отображающей потребности устройства.
Ну под очистить, наверное подразумевается обнулить...
Процедура в таком случае выдает результат 2097152, что соответствует цифре 2 мегабайта и не совпадает с цифрой полученной возведением двойки в степень равную числу обнуленных разрядов.
Так какой же способ правильный?
P.S. Возведение двойки в степень 21 (17 адресных + 4 служебных бита) тоже дает цифру 2097152. Но меня смущает то, что в расчете адресуемого пространства присутствуют служебные биты...
Служебные биты тоже считаются за 0. Так что 17+4=21 бита.
Вернее служебные биты обнуляют. В спецификации все хорошо расписанно.
Это всеравно чо взять с обратным знаком.
Допустим, я запрашиваю у системы эти 2 мега в пространстве памяти, она мне выдает адрес, а дальше? Я его должен записать в BAR со смещением относительно служебных битов или прям поверх них?
Напоминаю что адресс должен быть выравнен по требуемому размеру.
Так что служебные биты будут 00. Пишешь прямо поверх них. BAR регистр сам выставит служебные биты если они не 0. За исключением бита Prefetch. Его я бы порекомендовал выставить в 1 вручную.
А вообще почитай спецификацию PCI 3.0 там одну особенность задокументировали которая раньше не входила в спецификацию. Да и другии расписанны.
Что перед записью в BAR, адресное значение должно быть сдвинуто влево на количество служебных бит? В данном случае на 4?
|11111000111|00000000011100000|0|00|0|
То устройство обнулит биты.
|11111000111|00000000000000000|0|00|0|
И будет считать что адресс равен F8E00000h
Поэтому адресс и должен быть выровнен. Т.е принадлежать числам вида.
xxy000000
Где x любое 0-F. А y c обнуленным младшим битым те одно из 0 2 4 6 8 A C E
Или другими словами адрес должен быть равен n*Size.
нельзя ли это пояснить...
И что значит поле ШИНА? ЭТО что номер слота?
Я "читал" спецификацию PCI 2.2 но к сожалению моего английского не хватает чтобы понять о чём там (особенно интересует раздел 3.2.2.3.2).
Вообще можно просто(не задумываясь о том что значит шина и т д) в трёх вложенных циклах менять значения (шина, устройство, функция) и проверять существует ли устройство или нет? Будет информация верна?
Шина это шина. В чипсете системные устройства которы уже вшиты в чипсет IDE(SATA) контроллер, контроллер памяти, контроллер USB, контроллер LAN и др. Расположенны на шине 0 это PCI шина или ее аналог не суть важно. Видео карта традиционно распологается на AGP или PCI-E обычно эта шина 1. На шине 0 в таком случии должен быть мост PCI-to-AGP или PCI-to_PCI[E].
мостов может быть много. И они могут быть цепными.
Классическая схема такая
+---контроллер памяти
+---контроллер дисков
+---USB контроллер
+---Другии
+---мост PCI-to-AGP
шина 1
+---видео карта
+---мост PCI-to-PCI
шина 2
+---Слот 1
+---Слот 2
+---Слот 3
+---Слот 4
+---Слот 5
тв тюнор
+--- функция1 тв тюнер
+--- функция2 fm тюнер
+--- может быть еще что нибуь
А вот в совремееном с PCI-express такая
+---контроллер памяти
+---контроллер дисков
+---USB контроллер
+---Другии
+---мост PCI-to-PCI-express
шина 1
+---видео карта
+---мост PCI-to-PCI-express
шина 2
+---второй слот PCI-express
+---мост PCI-to-PCI-express
шина 3
+---третий слот PCI-express
+---мост PCI-to-PCI
шина 4
+---Слот 1
+---Слот 2
+---Слот 3
+---Слот 4
+---Слот 5
тв тюнор
+--- функция1 тв тюнер
+--- функция2 fm тюнер
+--- может быть еще что нибуь
Слот он больше всего соответствует термину устройство.
По поводу проверять в трех циклах не задумываясь. Нужно перебирать шины устройства и функции так что три цикла понадобиться по любому.
Просто это долго пребирать все 65536 значений. Поэтому я советую узнать максимальное число шин. Через PCI BIOS или PIR или ACPI или считать мосты PCI-to-PCI во время перебора. мосты AGP и PCI-Express и PCI если не путаю все подпают под один класс PCI-to-PCI.
следовательно алгоритм :
1)перебор по шинам и девайсам
2)читаем DID
3)если DID=0хffff , то пункт 1 , если нет , то :
4)перебор функций и чтение всей конф. инфы . если у всех функций конфигурация одинакова , то объединяем в одно ус-во с адресом (*,*,0) . такое бывает когда разработчики неправильно настраивают (или забывают) мост PCI-LocalBus устройства .
Можно еще проверить если у 0 функции. Тим мультифункционального устройства то перебирать если нет, то не надо.
правильно ли я понимаю что если найдена несуществующая функция то все функции за ней тоже не существуют(для МФ устройства)?
В 14-м посте (03.06.2009) Вы писали "Снял я лог работы с PCI абонентом"
Уточните, пожалуйста, какими средствами это можно сделать и как?
Я понимаю, что этим можно контролировать наличие своей PCI-платы и правильность ее конфигурации, как бы подобие монитора... Мне необходим такой.
Как это можно сделать?
Написать программу самому или найти уже готовую.
В зависимости от задачи, можно написать и монитор. "Свое" PCI устройство, если оно разработано согласно спецификации PCI, ничем не будет отличаться от любого другого в плане работы с конфигурационным пространством.
Опять же все зависит от того, под чем запускать собрались. Я писал не под интеловскую платформу. С операционкой и без.
могут . поэтому нужен быстрый опрос по таймеру . один раз в секунду вполне хватит .
- автор проги не осилил пункт "Свойства" контекстного меню Проводника
- тем, кому надо задавать такие вопросы как то по барабану, что процессы жрут много памяти. А то потом прибьют пару системных процессов, потому что слишком много памяти забрали и удивляться почему система повисла.
- Если бы говорилось про "размер свободного пространства", то это ещё имело бы смысл, но размер диска... Уже появились диски с самоизмеяющимся размером?
- см. первую цитату.
Спамер не учёл, что это не "форум домохозяек"...
Оно и логично, ведь люди с чуть более чем нулевым уровнем интеллектуального развития способны найти работу отличную от спамерства. Остальные дибилы - велкам! )
пытаюсь запрогить звук под дос на встроенной звуковухе. Даже и не спрашивайте зачем :)
в общем, PCI High definition audio (HDA) устройство выдало такую конфу:
[SIZE="1"]
00 : 86 80 D8 27 06 00 10 00 01 00 03 04 08 00 00 00
10 : 04 00 10 F2 00 00 00 00 00 00 00 00 00 00 00 00
20 : 00 00 00 00 00 00 00 00 00 00 00 00 58 14 02 A0
30 : 00 00 00 00 50 00 00 00 00 00 00 00 10 01 00 00
40 : 01 00 00 03 07 00 00 00 00 00 00 00 00 00 00 00
50 : 01 60 42 C8 00 00 00 00 00 00 00 00 00 00 00 00
60 : 05 70 80 00 00 00 00 00 00 00 00 00 00 00 00 00
70 : 10 00 91 00 00 00 00 00 00 08 10 00 00 00 00 00
80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C0 : 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
F0 : 00 00 00 00 00 00 00 00 86 0F 01 00 00 00 00 00
[/SIZE]
bar 10h - смотри на картинке.. (из спецификации)
bar 40h - значит ли он, что можно переключиться между конф пр-вом HDA и AC97?
как получить доступ r/w к регистрам на которые указывает бар 10h??
(желательно пример на asm / pascal)
функция ниже выдает мне регистр из конф пр-ва устр-ва
var inf:byte;
begin
asm
mov ax,$8000
mov al,bus
db $66;shl ax,16
mov ax,index
and ax,00fch
mov ah,deviceid
shl ah,3
add ah,func
mov dx,0cf8h
db $66;out dx,ax
mov ax,index
and ax,3
mov bl,8
mul bl
mov cx,ax
mov dx,0cfch
db $66;in ax,dx
db $66;shr ax,cl
mov inf,al
mov failed,false
db $66;xor ax,ax
mov dx,0cf8h
db $66;out dx,ax
end;
lookup_hw:=inf;
end;
:eek:
Позвольте освежить данную тему.
Я никак не пойму с регистром XROMBAR - Expansion ROM Base Address register, что по смещению 30h в конфигурационном пространстве PCI.
На первой странице данной ветки есть описание, читал спецификацию и Салихана.
Что значит фраза в спецификации PCI Firmware, "если регистр XROMBAR реализован, то содержимое образа ROM копируется в память и запускается инициализирующая функция"
Значит ли эта фраза, что если в ответ на запись одними 1, он вернёт ненулевой значение, то это он реализован.
Меня волнует бит 0. Вот если он вернётся 0. То всё равно POST компа скопирует образ и запустит инициализирующую функцию???
Значит ли этот бит, что просто сам ROM карты расширения не будет доступен для записи и чтения через отображение на память. Но при этом POST всё равно запустит код из образа, находящегося в нём???
Пожалуйста, нужен ответ!!! :facepalm:
ром карты никак не может быть доступен . доступен образ в оперативке до инициализации и иногда после , тк. процедура инициализации часто затеняют соответствующую область памяти .
Ответьте, пожалуйста, ещё на один вопрос.
А как тогда происходит работа с ROM? Кто потом включает этот бит?
Я имею ввиду, как используется возможность перепрограммирования ROM (чаще всего в спецификациях через посылку определённых команд по смещению 555h на отображаемой области в памяти)?
Или даже просто нужно, чтобы весь ROM отображался в память ( а это порой объём до 1Мб).
бит в командном регистре устанавливается программой - биосом , операционной системой или драйвером .
работа с ром зависит от его типа (некоторые типы пзу не перепрошиваются в принципе) и от разработчика . поэтому необходимо иметь полную программную спецификацию устройства .
Делаю образ Extension PCI ROM. Прошиваю его в PCI-E плату. И с соответствующими изменениями в mini-PCI-E плату. Обе поочереди вставляю в слот PCI-E (для mini есть переходник).
Размер образа 32 Кбайта. В заголовке PCI указывается правильное число страниц, для отображаемого образа.
Заметил, что на обычной PCI-E плате отображается только 16Кбайт. Причем образ начинает работать, то есть противоречий с crc, подсчитанной от 32Кб нет. Но при прыжке на адрес за пределами 16Кбайт всё виснет. Кода там нет. Если не выходить за пределы 16Кб, то всё работает.
Для платы mini-PCI-E такого не происходит и весь код отображается и работает нормально.
Вопрос: это особенность ПЛИС платы PCI-E? Это разработчики платы PCI-E так сделали?
Но как тогда считается crc от образа, ведь в заголовке PCI указан размер отображаемого образа и crc должно счтаться от него, а если она не совпадает, то и образ запускаться не должен...