Der PCI Configuration Header
|
Dieser Abschnitt gibt einen kurzen Überblick über die für das LogiCore PCI Interface relevanten Teile des PCI Configuration Headers und vermittelt so einen Eindruck von den Möglichkeiten und technischen Features des LogiCore PCI Interfaces (und PCI-Geräten im allgemeinen).
|
Übersicht
Im PCI Configuration Header werden die Art, das Verhalten und der Ressourcenbedarf der PCI-Karte definiert.
Dieser Abschnitt stellt den PCI Configuration
Header aus der Sicht des LogiCore PCI Interfaces vor, d.h. es werden die Konfigurationsmöglichkeiten erläutert, aus denen die Register des PCI Configuration Headers (siehe Abbildung) gebildet werden. Alle Einstellungen werden in der Datei cfg.vhd vorgenommen.
Abb.: PCI Configuration Header (Typ 0)
Die Vendor ID
ist die von
PCI SIG
zugewiesene Herstellernummer. Die Device ID und die Revision ID wird dagegen vom
Hardware-Hersteller vergeben und identifiziert den Typ und die Revision der
PCI-Karte.
--------------------------------------------------------------
-- Configure Device, Vendor ID, Class Code, and Revision ID
--------------------------------------------------------------
-- Device ID and Vendor ID
cfg_int(151 downto 120) <= X"030010ee" ;
-- Class Code and Revision ID
cfg_int(183 downto 152) <= X"0b400000" ;
Der Class Code ist in drei 8 Bit große Felder unterteilt (Base Class, Sub Class, Programming Interface), die das
PCI-Gerät nach einem von
PCI
SIG vorgegebenen Schema gemäß seiner Funktion klassifiziert. Das
Betriebssystem kann mithilfe dieser Angaben im Idealfall Standardtreiber bereitstellen und die
PCI-Karte (z.B. VGA-kompatible Grafikkarte) betreiben.
Im obigen Code ist die
Base Class 0x0b (Prozessor) und die Sub Class 0x40 (Co-Prozessor).
Die Subsystem Vendor ID wird ebenfalls von
PCI SIG vergeben, während die Subsystem (Device) ID vom Hardware-Hersteller zugeordnet wird.
Eine komplexe PCI-Karte kann mehrere Subsysteme enthalten, die um das
gleiche PCI-Interface herumentwickelt sind. Unter Zuhilfenahme der beiden
Register kann das Betriebsystem trotz des gemeinsamen Buszugangs zwischen den
Subsystemen (ggf. verschiedener Hersteller) unterscheiden und die richtigen
Treiber laden.
Der Wert 0 zeigt an, dass kein Subsystem vorhanden ist.
--------------------------------------------------------------
-- Configure Subsystem ID and SubVendor ID
--------------------------------------------------------------
-- Subsystem ID and SubVendor ID
cfg_int(215 downto 184) <= X"00000000" ;
-- External Subsystem ID and Subvendor ID
cfg_int(114) <= DISABLE ;
Das LogiCore PCI Interface
implementiert nur die ersten drei der insgesamt sechs Basisadressregister, die zur Reservierung von I/O-Portadressen oder I/O-Speicheradressräumen (Memory Mapped I/O) verwendet werden. Beim Einschalten des Systems enthalten sie Angaben über die Größe der benötigten Adressräume und über gewisse
Speichereigenschaften. In der Konfigurationsphase werden die Register
ausgelesen, eine geeignete Anfangsadresse für jeden angeforderten Bereich ermittelt und
in das entsprechende Register zurückgeschrieben.
--------------------------------------------------------------
-- Configure Base Address Registers
--------------------------------------------------------------
-- BAR0
cfg_int(0) <= DISABLE ;
cfg_int(32 downto 1) <= SIZE2G ;
cfg_int(33) <= NOFETCH ;
cfg_int(35 downto 34) <= TYPE00 ;
cfg_int(36) <= MEMORY ;
-- BAR1
cfg_int(37) <= DISABLE ;
cfg_int(69 downto 38) <= SIZE2G ;
cfg_int(70) <= NOFETCH ;
cfg_int(72 downto 71) <= TYPE00 ;
cfg_int(73) <= MEMORY ;
-- BAR2
cfg_int(74) <= DISABLE ;
cfg_int(106 downto 75) <= SIZE2G ;
cfg_int(107) <= NOFETCH ;
cfg_int(109 downto 108) <= TYPE00 ;
cfg_int(110) <= MEMORY ;
Jedes Basisadressen-Register wird durch fünf Angaben spezifiert:
Zeile |
Bedeutung |
mögliche Werte |
1 |
Register verwenden? |
ENABLE DISABLE |
2 |
Größe des Adressraums |
SIZE2G SIZE1G SIZE512M SIZE256M SIZE128M SIZE64M SIZE32M SIZE16M
SIZE8M SIZE4M SIZE2M SIZE1M SIZE512K SIZE256K SIZE128K SIZE64K SIZE32K
SIZE16K SIZE8K SIZE4K SIZE2K SIZE1K SIZE512 SIZE256 SIZE128 SIZE64 SIZE32
SIZE16 |
3 |
Prefetchbarer Speicher? |
PREFETCH NOFETCH IO_PREFETCH |
4 |
Einordnung im Gesamtadressraum und Registerbreite |
TYPE00 (TYPE01) TYPE10 IO_TYPE |
5 |
IO- oder Speicheradressraum |
IO MEMORY |
I/O-Ports oder I/O-Speicher
Der PCI-Standard unterstützt, abgesehen vom
Configuration Space, wie vom PC her bekannt zwei getrennte Adressräme: I/O Space
und Memory Space.
Die Spezifikation empfiehlt jedoch nachdrücklich, die Karte
ausschließlich in den Memory Space des Rechners einzugliedern: In PCs ist der Adressraum der I/O-Ports beschränkt und ein Relikt vergangener Zeiten.
Andere moderne Architekturen, insbesondere die "echten" RISC-Rechner, haben nur einen
Addressraum, in den die periphere Hardware Bereiche für sich belegt (Memory Mapped I/O).
Entscheidet man sich z.B. aus
Kompatibilitätsgründen dennoch für die I/O-Ports, sind bei der
LogiCore PCI Interface Konfiguration die jeweiligen Konstanten, die mit "IO_"
beginnen, zu benutzen.
|
minimale Größe |
maximale Größe |
Memory Space |
16 Bytes (SIZE16) (4 32Bit-Register) |
2 GBytes (SIZE2G) |
I/O Space |
16 Bytes (SIZE16) (4 32Bit-Register) |
256 Bytes (SIZE256) (64 32Bit-Register) |
Die PCI Spezifikation empfiehlt, im Fall des Memory Mapped I/O mind. einen 4 KByte großen Bereich zu belegen, um die Anzahl der Bitvergleiche
im Adressdekoder des PCI-Interfaces in vernünftigem Rahmen zu halten.
Das Prefetch-Attribut
Das gesetzte Prefetch-Attribut erlaubt der
PCI-Bridge vorauseilende spekulative Lesezugriffe (Read Prefetching) und das Zusammenfassen bestimmter Schreibzugriffe (Byte Merging).
Ein im PCI-Gerät
realisierter Speicherbereich darf mit dem Prefetch-Attribut markiert werden,
wenn die folgenden Bedingungen für einen "wellbehaved memory" erfüllt sind:
- Keine Seiteneffekte bei einem Lesezugriff: Ein Lesezugriff ändert nicht
den Inhalt des Speichers oder den Zustand des PCI-Geräts.
Bespiel: Das Lesen aus einem RAM hat keine Seiteneffekte, während das Lesen aus einem FIFO-Speicher den Zustand des FIFO-Speichers ändert: Die gelesenen Daten sind anschließend nicht mehr in der FIFO. Automatisches spekulatives Lesen zerstört unvorhersehbar Daten.
- Bei einem Lesezugriff sind immer alle Bytes auf voller Busbreite
(32 Bit bzw. 64 Bit) gültig. Bei PCI gibt es die Möglichkeit, Bytes innerhalb
des Datenworts zu maskieren.
- Das PCI-Gerät arbeitet auch dann korrekt, wenn die PCI-Bridge einzelne
Schreibzugriffe zusammenfasst (Byte Merging).
Beispiel: Der Prozessor führt
zwei 16 Bit Schreibzugriffe aus, den ersten auf die Adressen 0x00000100 und
0x00000101, den zweiten auf die Adressen 0x00000102 und 0x00000103, wobei ein 16 Bit Zugriff ein 32 Bit Zugriff mit zwei maskierten Bytes ist. Da die
Adressen aufeinanderfolgen, kann die PCI-Bridge die beiden
16 Bit Schreibzugriffe zu einem 32 Bit Schreibzugriff zusammenfassen.
Einordnung im Gesamtadressraum und Registerbreite
- TYPE00: 32Bit-Register. Die Anfangsadresse liegt in den unteren 4 GByte des
gesamten Speicheradressraums und ist an 32 Bit ausgerichtet, d.h. durch 4
teilbar. Die unteren zwei Bits der 32 Bit Adresse sind 0 bzw. werden ignoriert.
- TYPE10: 64Bit-Register. Die zugewiesene Startadresse liegt in einem
264 Speicheradressraum. Voraussetzung ist, daß das PCI-Gerät die
64 Bit Adressierung (Dual-Address Command (DAC))unterstützt. Das
Basisadressregister braucht dementsprechend auch zwei Doppelworte usw.
(hier nicht relevant)
- TYPE01 ist seit der 2.2 PCI-Spezifikation nicht mehr erlaubt und daher
reserviert. Der Speichertyp erzwingt, dass die Anfangsadresse in den ersten 1
MByte des Speicheradressraums liegt.
Alle drei Register sind optional und nur für Busmaster relevant, d.h. für
PCI-Geräte, die - nach entsprechender Initialisierung - selbstständig den Bus
anfordern und Datentransfers durchführen können.
Das read-only Register
Max_Lat gibt in Zeitschritten von 250 ns an,
wie oft das PCI-Gerät den Bus
benötigt. Eine intelligente programmierbare Busarbitrierung kann mit dieser
Angabe sinnvolle Prioritäten bei konkurrierenden Busanforderungen mehrerer
PCI-Geäte setzen. Der Wert 0 zeigt an, dass das Gerät keine besonderen
Anforderungen hat.
Das read-only Register Min_Gnt kann zur Optimierung von
Bursttransfers verwendet werden. Es gibt in 250 ns Schritten an,
für wie
lange der Busmaster den Bus benötigt (wenn er ihn zugeteilt bekommen hat),
um performant arbeiten zu können. Der Wert 0 zeigt an, dass das Gerät keine
diesbezüglichen Anforderungen stellt.
Auf der Basis des Wertes im
Min_Gnt-Register kann die PCI-Konfigurationssoftware im Wissen um die
tatsächliche Bustaktfrequenz einen Wert für das Latency Timer Register berechnen
und dort hineinschreiben, sofern es überhaupt im betreffenden PCI-Master
implementiert ist. Der Latency Timer (LT) gibt die minimale Zeit in PCI-Takten
an, für die der PCI Master den Bus für Bursttransfers benutzen darf. Ablauf
(vereinfacht):
Der Initiator fordert den Bus für einen Bursttransfer an
(REQ-Leitung des PCI-Slots). Die Busarbitrierung teilt den Bus zu (GNT-Leitung des PCI-Slots), wenn er frei
ist und kein anderes wartendes Gerät Vorrang hat. Der Master hat den Bus nun für
mindestens LT PCI-Takt-Zyklen garantiert für sich reserviert. Werden dem Master im laufenden Transfer die
Busrechte entzogen, muss er nicht sofort unterbrechen und den Bus wieder
freigeben, sondern darf noch solange fortfahren, bis LT Zyklen erreicht sind. Wenn kein anderes
Gerät den Bus braucht, darf er natürlich auch einen längeren (beliebig langen)
Bursttransfer durchführen.
--------------------------------------------------------------
-- Configure MAX_LAT MIN_GNT
--------------------------------------------------------------
-- MAX_LAT and MIN_GNT
cfg_int(231 downto 224) <= X"00" ;
cfg_int(223 downto 216) <= X"00" ;
-------------------------------------------------------------
-- Configure other PCI Header options
-------------------------------------------------------------
-- Latency Timer Enable
cfg_int(112) <= DISABLE ;
Der PCI-Bus
verfügt über vier Interruptleitungen INTA bis INTD, die im Unterschied zum
ISA-Bus von mehreren Geäten getrieben werden dürfen.
Das Interrupt
Pin Register gibt an, ob und welche bzw. wieviele der vier Leitungen für die Signalisierung von
Interrupts verwendet werden. Das LogiCore PCI Interface unterstützt bei Bedarf
die Signalisierung eines Interrupts auf der Leitung INTA des PCI-Busses.
Das Interrupt Line Register gibt an, welchem Eingang des Interruptcontrollers die
PCI-Interruptleitung zugeordnet ist.
-------------------------------------------------------------
-- Configure other PCI Header options
-------------------------------------------------------------
-- Interrupt Enable
cfg_int(113) <= DISABLE ;
Beispiel: Für den Prozessor eines PCs sind die vier PCI-Interruptleitungen unsichtbar. Sie werden vielmehr mit einem Interruptrouter zusammengefasst und auf die Eingänge des eigentlichen
Interruptcontrollers (IRQ0 - IRQ15) abgebildet. Der zugeordnete IRQ, d.h. ein
Wert zwischen 0x00 und 0x0F, wird im Interrupt Line Register eingetragen. Erst
dadurch kann das Betriebssystem bzw. der Gerätetreiber durch Auslesen des
Interrupt Line Registers überhaupt feststellen, in welche Zeile der
Interrupttabelle er seine Interrupt Service Routine eintragen muss.
Die Abbildung zeigt eine typische Anordnung in heutigen PCs. Links im Bild sind die PCI-Geräte schematisch dargestellt. Einfache Devices (Single Function) verwenden die Leitung INTA, komplexe Geräte (Multi Function) darüberhinaus auch weitere Leitungen. Die Interruptleitungen der Steckplätze werden auf elektrischer Ebene ausgewogen zusammengefaßt und dann einem programmierbaren Interruptrouter (Teil der PCI/ISA-Bridge) auf die IRQs abgebildet.
Abb.: Empfohlenes Routing der PCI-Interruptleitungen für einen Router mit nur vier Eingängen
(Quelle: PCI System Architecture)
Für komplexe PCI-Geräte sind unter Umständen
mehr Angaben über die Hardware nötig als der verbindliche Teil des PCI
Configuration Headers vorsieht (z.B. PCI Power Management Interface, AGP,
Message Signaled Interrupts). In diesem Fall wird der Capability List Pointer
benutzt, um auf den Beginn einer Datenstruktur zu verweisen, die hinter dem
vorgeschriebenen Teil des PCI Configuration Headers liegt. Diese Datenstrukturen
haben je nach Art der Hardware (Beispiele wie gehabt) einen festgelegten
Aufbau.
Das LogiCore PCI Interface besitzt die Möglichkeit, diese Erweiterung
zu nutzen, jedoch geht die genaue Erläuterung über den Rahmen dieser übersicht
hinaus.
-------------------------------------------------------------
-- For advanced users only.
-------------------------------------------------------------
-- Capability List Enable
cfg_int(116) <= DISABLE ;
-- Capability List Pointer
cfg_int(239 downto 232) <= X"00" ;
-- User Config Space Enable
cfg_int(118) <= DISABLE ;
Erkennt ein (Intel x86-basierter) Prozessor einen Interrupt an seinem Interrupteingang, reagiert er
darauf, indem er den Interruptvektor vom Interruptcontroller abfragt. Auf dem
PCI-Bus wird dazu ein spezieller Interrupt Acknowledge Buszyklus generiert. Im
typischen PC-Design ist der antwortende Interruptcontroller in der South Bridge
integriert, die nur über den PCI-Bus zu erreichen ist. Das LogiCore PCI
Interface kann diese speziellen Interrupt Acknowledge
Kommandos auf dem PCI-Bus erkennen und darauf reagieren. Eine mögliche
Anwendung dieser Funktion wäre die Verwendung des LogiCore PCI Interfaces zum
Bau einer eigenen PCI-Bridge. Very advanced!
-------------------------------------------------------------
-- For advanced users only.
-------------------------------------------------------------
-- Interrupt Acknowledge
cfg_int(240) <= DISABLE ;
Autor: gkemnitz, Letzte Änderung: 14.04.2011 15:09:59