Устройство PCI



PCI - Peripheral Component Interconnectинтерфейс шины, присоединяющей периферийные устройства к материнской плате.


PCI состоит из 32 электрических линий, каждая из которых представляет бит информации: 0/1. PCI работает с частотой 33MHz. Это означает, что данные в линиях могут меняться 33 тысячи раз в секунду.


Устройства разделяют линии шины. Каждое устройство владеет доступом ко всей шине в течение некоторого времени.


Арбитраж шины – механизм, который определяет, которое устройство может владеть шиной в данный момент.


Устройства могут сообщаться со своим драйвером, который является частью программного обеспечения, работает в контексте операционной системы и управляет соответствующим устройством. Для каждой операционной системы должна быть специальная версия драйвера.


Для сообщения с драйвером устройство имеет линию прерывания (IRQ line), которая используется для сообщения процессору, что оно должно вызвать драйвер для обработки им события.


При обработке события драйверу может понадобиться прочитать данные с устройства (например, для чтения/записи принятого/передаваемого сетевого пакета или содержимого дисплея). Для передачи данных PCI устройство имеет две возможности: передача данных через некоторый порт ввода/вывода или через разделяемый, предварительно выделенный, регион памяти. Линия прерывания и регион памяти называются ресурсами периферийного устройства.


Регион памяти – это часть основной памяти компьютера RAM, так что драйвер просто копирует данные из этой памяти или в нее. Соответствие регионов памяти устройствам задается BIOS’ом.


BIOS (Basic Input and Output System) – отвечает за загрузку системы и обеспечивает ее некоторыми базовыми возможностями, например, поддержкой примитивного адаптера дисплея. Одна часть BIOS’а проходит по всем присоединенным PCI-устройствам и предоставляет им ресурсы памяти, которые им требуются, путем программирования регистров базового адреса. После этого BIOS грузит операционную систему, которая нумерует все PCI-устройства и существующие ресурсы памяти.


Каждое PCI-устройство идентифицируется device ID и vendor ID, которые содержатся в первых 64 битах конфигурационного пространства каждого PCI-устройства. После считывания этой информации операционная система ищет по ней подходящий драйвер устройства.


DMAC (Direct Memory Access Controller) – процессор, который знает, как копировать данные из одного места в другое. Используется драйверами для копирования данных без загрузки CPU.


Конфигурационное пространство PCI


PCI BAR (Base Address Register)


Адрес

31 ... 24

23 ... 16

15 ... 8

7 ... 0

0x00

DeviceID

VendorID

0x04

Status

Command

0x08

Class Code

Revision ID

0x0C

BIST

Header Type

Latency Timer

Cash Line Size

0x10

Base Address Register 1

0x14

Base Address Register 2

0x18

Base Address Register 3

0x1C

Base Address Register 4

0x20

Base Address Register 5

0x24

Base Address Register 6

0x28

Card bus CIS pointer

0x2C

SubsystemID

Subsystem Vendor ID

0x30

Expansion ROM Base Address

0x34

Reserved

Capabilities
pointer

0x38

Reserved

0x3C

Max_Lat

Min_Gnt

Interrupt Pin

Interrupt Line


Таблица 1. Первые 64 байта конфигурационного адресного пространства PCI (в соответствии с PCI Local Bus Specification 2.2)


Три адресных пространства:

- память (LDR, STR – чтение/запись из памяти/в память)

- порты ввода вывода

- конфигурационное пространство PCI


I/O ports – определенные адреса (размер адреса 12 битов), на каждый адрес назначена определенная функция


0xcf8 - PCI CONFIG_ADDRESS

0xcfc - PCI CONFIG_DATA


При записи в конфиг.пр-во PCI сначала в I/O порт 0xcf8 записывается адрес регистра, а затем в I/O порт 0xcfc записываются данные, предназначенные для записи в заданный таким образом регистр конф.пр-ва PCI.


При чтении из конфиг.пр-во PCI сначала в I/O порт 0xcf8 записывается адрес регистра, а затем из I/O порт 0xcfc читаются данные, содержащиеся в заданном таким образом регистре конф.пр-ва PCI.



Формат CONFIG_ADDRESS:

0x80000000 | bus << 16 | device << 11 | function <<  8 | offset

Чтение/запись в порт:
x=inb(addr), outb(addr, data), outw(), outl()