Projekte.PCI-Tutorial-Konfiguration (Struktur)


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)

Device ID, Vendor ID und Revision ID

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" ;

Class Code

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).

Subsystem Vendor ID, Subsystem Device ID

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 ;

Base Address Register

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.

Das Max_Lat-Register, das Min_Gnt-Register und der Latency Timer

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 ;

Interrupt Pin und Interrupt Line

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)

New Capabilities

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 ;

Interrupt Acknowledge

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


 TU Clausthal 2020  Impressum