Markus Fichtenbauer
Torsten Lang
Michael Schwingen
Der PCI-Bus (Part 1)
Heute ist es soweit: Mit dem Milan und dem Hades stehen den ATARI-Anwendern
inzwischen zwei Rechner zur Verfügung, die einen PCI-Bus besitzen.
Schon bald soll ein Falcon-PCI-Adapter erscheinen, und eines Tages wird
auch der französische Phenix mit PCI-Bus zu erhalten sein. Alles deutet
also darauf hin, daß PCI-Karten nun auch für das TOS angepaßt
werden. Erfreulicherweise ist die Entwicklung in diesem Bereich soweit
vorangeschritten, daß ein gemeinsames PCI-Bios entwickelt wurde,
das ermöglicht, daß einmal angepaßte Treiber auf allen
o.g. Systemen laufen werden.
In unserem mehrteiligen Kurs wollen wir Sie über die Funktionsweise
des PCI-Busses und anschließend die Programmierung des TOS PCI-Bios
informieren.
Allgemeines:
Der Peripheral Components Interconnect (PCI) Bus wurde ursprünglich
für IBM-kompatible PCs entwickelt, da dringend die Notwendigkeit eines
schnellen, prozessorunabhängigen Bussystems bestand. Seither hat sich
dieser Bus auch für andere Rechnerwelten etabliert (wie z.B. die aktuellen
Macintosh-Modelle auf Basis des PowerPC, diverse Workstations mit DECs
Alpha-Prozessor oder aber auch die aktuelle UltraSparc von SUN).
Auch die Entwickler des Hades und des Milan haben an diese wirklich universelle
Schnittstelle gedacht. Diese Entwicklung führte dahin, daß man
nun tatsächlich dieselben Erweiterungskarten auf unterschiedlichen
Rechnerplattformen nutzen kann - sofern jeweils Treiber für das betreffende
System verfügbar sind. Daher ist es längst an der Zeit, sich
einmal näher mit dem PCI-Bus zu beschäftigen. Diese erste Folge
soll einen Überblick der Möglichkeiten des PCI-Bus schaffen,
die zweite Folge beschreibt dann die einzelnen Register für die Initialisierung
und Konfiguration von PCI-Karten, und die abschließende dritte Folge
befaßt sich dann mit der Portierung und Implementierung des vom PC
her bekannten PCI-BIOS für ATARI-kompatible Rechner am Beispiel von
Hades und Milan.
Der PCI-Bus ist für 32 Bit breite Daten bei maximal 33 MHz spezifiziert
und ist optional auf 64 Bit und/oder 66 MHz erweiterbar. Der Takt darf
aber im Prinzip einen beliebigen Wert zwischen 0 und 33 MHz annehmen.
Bei 33 MHz und 32 Bit Datenbreite sind theoretische Übertragungsraten
von bis zu 132 MB/s möglich, und in der Praxis sind tatsächlich
Werte nahe diesem theoretischen Maximum erreichbar.
Nach der elektrischen Spezifikation können an einem PCI-Bus bis zu
vier Slots neben dem Hostsystem untergebracht sein. Über eine PCI-Bridge
läßt sich dann noch ein weiterer Bus anhängen. Falls dies
wieder ein PCI-Bus ist, kann man das Spiel auch mehrfach wiederholen.
Jedes PCI-Gerät kann mehrere unabhängige Funktionen beinhalten
(multifunction devices), die sich auch unabhängig über den Bus
ansprechen lassen. Die meisten derzeit erhältlichen Geräte sind
allerdings sogenannte 'single function devices'.
Multi function devices verhalten sich prinzipiell wie mehrere single function
devices, nur, daß eben die Configuration Bereiche der einzelnen Funktionen
dieser Karten anders angesprochen werden.
Bei den Multifunktionskarten kann man zwei von Grund auf verschiedene Versionen
unterscheiden:
1. Nur ein einziger Bus - die Konfigurationsbereiche solcher PCI-Karten
liegen jeweils 256 Bytes auseinander (d.h. die Adressleitungen spiegeln
einfach Register (Bit 0-7) und Funktionsnummer (Bit 8-15) der Karte wieder.
2. PCI2PCI-Bridge mit single function devices oder multi function devices
vom Typ 1 am zweiten Bus - so etwas kommt z.B. bei Kombikarten wie Ethernet
+ SCSI vor. Da die Busnummer hier über die Adressleitungen A16-23
ausgewählt werden würde, lassen sich solche Karten beim Hades
wahrscheinlich nicht oder nur eingeschränkt verwenden (weil die Konfigurationsbereiche
ja auf wenige KB beschränkt sind).
Die PCI-Hardware
Für die grundlegenden Funktionen des PCI-Bus werden insgesamt 47 Pins
für Slave-Adapter sowie 49 Pins für Master-Adapter benötigt.
Dazu kommen die Anschlüsse der Versorgungsspannung. Auf eine Aufzählung
aller Signale möchte ich hier allerdings verzichten, da diese den
Artikel sichtlich sprengen würden. Deshalb sollen nur die wichtigsten,
in den Abbildungen verwendeten Signale näher erläutert werden:
AD[0..31] - Address/Data
Adressen und Daten werden gemultiplext übertragen. Die einzelnen Bytes
des 32-Bit-Wortes werden über die Leitungen /C/BE[0..3] freigegeben.
/C/BE[0..3] - Command/Byte Enable
Enthält in der Adressphase das Buskommando (verschiedene Lese- und
Schreibarten) und in der Datenphase das Signal Byte Enable für die
Datenleitungen.
IDSEL - Initialization Device Select
Chip Select für Initialisierung und Konfiguration der PCI-Karte. Für
jeden PCI-Slot ist eine eigene Leitung vorhanden.
/REQ - Request, wird nur für Busmastering verwendet.
Busanforderung, für jeden Slot ist eine Leitung vorhanden.
/GNT - Grant, wird nur für Busmastering verwendet.
Buszuteilung, für jeden Slot ist eine Leitung vorhanden.
/INTA - Interrupt Request A
Anforderung eines Interrupts bei single function devices.
/INTB, C, D - Interrupt Request B, C, D
Diese Interruptleitungen dürfen nur von Geräten mit mehreren
Funktionseinheiten (multi function devices) verwendet werden.
Die restlichen Signale dienen mehr oder weniger der Steuerung während
den verschiedenen Adress- und Datenphasen und deren Synchronisation. Näheres
findet man in der PCI Local Bus Specification und den PCI System Design
Guides, einen guten Überblick kann man sich aber auch mittels der
Elrad-Hefte 3/97 und 4/97 verschaffen.
Da wir hier nicht neue PCI-Karten entwickeln möchten, sondern aus
dem PC-Bereich bereits vorhandene Karten auch dem Hades, Milan und anderen
kompatiblen ATARI-Rechnern schmackhaft machen möchten, verzichten
wir hier auf weitere Hardware-Details, die für Treiber-Anpassungen
nicht relevant sind. Die korrekte Verarbeitung der Signale sollte ja ohnehin
von den in den Rechnern vorhandenen PCI-Bridges übernommen werden.
Wer aber trotzdem (oder gerade deswegen) eigene Karten entwickeln möchte,
sollte sich Datenblätter der PCI-Bridges von AMCC[4] und PLX[5] besorgen.
Wer das PCI-Busprotokoll selbst implementieren möchte, benötigt
dafür relativ schnelle CPLDs oder FPGAs. Hersteller wie Xilinx[6]
oder Lattice[7] bieten dafür auch Beispiel-Sourcen an.
DMA am PCI-Bus:
Grundsätzlich kann jedes beliebige PCI-Gerät als Busmaster auftreten.
Als Busmaster kann dieses PCI-Gerät dann selbständig Daten aus
seinem eigenen Speicherbereich in den Systemspeicher des Host-Rechners
übertragen. Diese Art der Hintergrundverarbeitung entlastet den Prozessor
des Host-Rechners sehr stark. Deshalb sollten alle PCI-Geräte, die
große Datenmengen zu transportieren haben, oder aber schnelle Transfers
erfordern, als Busmaster auftreten können. Die DMA-Fähigkeit
des PCI-Bus benutzen z.B. SCSI-Controller oder auch moderne Netzwerkkarten,
um Daten schnell in den oder aus dem Hauptspeicher zu transportieren.
Die Vorteile bei Verwendung eines busmasterfähigen PCI-Gerätes
zeigen sich ganz besonders bei 'echten' Multitasking-Betriebssystemen,
da dort die gesparte Rechenzeit anderen Prozessen zur Verfügung gestellt
werden kann. Unter Single-Tasking unterliegt es dem Geschick des Programmierers,
aus der Busmaster-Fähigkeit eines PCI-Gerätes Vorteile zu ziehen.
Ein Zugriff, der nur auf das Ende einer Übertragung wartet, ist zwar
einfacher zu implementieren, verschenkt durch Leerlauf des Prozessors aber
wieder die gewonnene Zeit.
Das busmasterfähige PCI-Gerät fordert den Bus durch Setzen seiner
/REQLeitung an. Ein Master darf /REQ allerdings nur für seinen aktuellen
Zugriff benutzen, nicht aber, um sich den Bus auf Dauer zu sichern. Der
Bus Arbiter des Host-Rechners teilt diesem Gerät den Bus durch Setzen
des entsprechenden /GNT-Signals zu. Nachdem dem PCI-Gerät der Bus
zugeteilt wurde, kann dieses seinen DMA-Zugriff durchführen. Wenn
das PCI-Gerät nicht innerhalb einer bestimmten Zeit den Bus wieder
freigibt, kann der Host-Rechner durch das Wegnehmen der /GNT-Leitung den
Bus auch wieder frei bekommen. Der Busmaster muß dann nämlich
augenblicklich den Zugriff beenden.
Interrupts am PCI-Bus:
Auf dem PCI-Bus sind insgesamt vier "pegel"-getriggerte Interrupt-Leitungen
vorhanden (INTA...INTD). Alle Geräte mit nur einer Funktion dürfen
nur INTA verwenden, die anderen drei Leitungen sind für den Betrieb
sogenannter 'multi function devices' vorgesehen.
In der PCI-Spezifikation selbst ist die weitere Verarbeitung der Interrupts
nicht definiert und wird somit dem jeweiligen Boardhersteller überlassen.
Die Interruptleitungen der einzelnen Slots können daher entweder als
"durchgeschleifte" Busleitung (open drain) in jeder nur erdenklichen Kombination
verbunden sein, oder aber sie werden von jedem Slot einzeln an den entsprechenden
Interrupt Controller herangeführt. Nach einer Interruptanforderung
ist dann der jeweilige Treiber dieses PCI-Gerätes dafür verantwortlich,
die Ursache der Unterbrechungsanforderung zu beheben.
Im Gegensatz zum recht kranken Design des ISA-Busses ist es daher beim
PCI-Bus möglich, daß sich mehrere Karten eine Interruptleitung
teilen (shared interrupt) - Engpässe, wie man sie früher von
den DOSen her kannte, werden damit vermieden. Allerdings müssen dann
die eingesetzten Softwaretreiber für die PCI-Karten auch Interrupts
bearbeiten können, bei denen sich mehrere Geräte eine Interruptleitung
teilen. Mehr zu diesem Thema gibt es dann bei der Vorstellung des PCI-BIOS.
Die Implementation des PCI-Bus im Milan:
Auch der Milan hat einen PCI-Bus mit einer Datenbreite von 32 Bit bei maximal
33 MHz. Die Anbindung an die CPU erfolgt über eine PCI-Bridge der
Firma PLX.
Es sind insgesamt 4 Interruptleitungen vorhanden, die zyklisch zwischen
den Slots getauscht sind - dadurch bekommt bei single function devices
jede Karte einen eigenen Interrupt, und erst bei multi function devices
wird es nötig, Interrupts gemeinsam zu benutzen.
Interrupts werden über die Intel PCI-ISA-Bridge und die darin vorhandenen
Interrupt-Controller bearbeitet und als Autovektor-Interrupt an die CPU
weitergemeldet.
Die Busarbitrierung für die DMA-Zugriffe erfolgt in einem der Glue-Chips
- alle Slots (sowie die Onboard-Peripherie) sind busmasterfähig. Es
wird eine Arbitrierung mit rotierender Priorität verwendet, bei der
die Karte, die gerade den Bus besitzt, die niedrigste Priorität hat,
so daß eine Karte den Bus nicht komplett blockieren kann. Wenn
niemand den Bus anfordert, wird er bei dem Gerät, welches ihn zuletzt
besaß, geparkt - das spart Zeit, wenn danach das gleiche Gerät
den Bus wieder anfordert.
Erweiterungs-ROM auf PCI-Karten:
Die PCI-Spezifikation beschreibt auch einen Mechanismus, mit dem ein PCI-Gerät
einen exekutierbaren ROM-Code für eine gerätespezifische Initialisierung
usw. anbieten kann. Dieses ROM kann dabei mehrere verschiedene ROM-Images
beinhalten, um die verschiedensten Rechner und Prozessorarchitekturen zu
unterstützen.
Der OPENBOOT Standard für PCI sieht Fortran-Programme im ROM vor,
so daß der ROM-Code zwar langsam (weil interpretiert), aber dafür
prozessorunabhängig ist. Die andere Möglichkeit sind native ROM-Images
(für die jeweilige zu unterstützende Plattform), wovon die Hersteller
aber keinen Gebrauch machen (wohl weil sich dann nur noch schwer begründen
ließe, warum z.B. dieselbe Grafikkarte für einen PowerMac meist
100% teurer ist als für den Intel PC). Natürlich können
OPENBOOT-Images und native Images gemeinsam in einem ROM untergebracht
werden.
Am ATARI werden die ROMs auf den Karten im Moment zwar noch nicht genutzt,
aber dieser Umstand wird sich schon demnächst ändern.
Ein paar Worte zu Plug'n'Play:
Das Zauberwort 'Plug and Play' ist sehr eng mit dem PCI-Bus verbunden.
Denn erst hier ist das leidige Thema der Ressourcenvergabe für die
Hardware über ein geeignetes BIOS (PCI-BIOS) elegant lösbar.
Im Idealfall sieht die Installation einer neuen PCI-Karte also folgendermaßen
aus (im Gegensatz zum PC ist bei ATARI-kompatiblen ein nochmaliges (oder
gar mehrmaliges) Booten während der Installation NICHT notwendig ;-)
· Karte in einen freien Slot reinstecken
· Rechner starten, das PCI-BIOS konfiguriert die Karte
· Softwaretreiber für die PCI-Karte starten und fertig
Der PCI-Bus ist eigentlich selbstkonfigurierend definiert. Dafür beinhaltet
jedes PCI-Gerät einen Satz von Registern, die während des Boot-Vorgangs
ausgelesen werden können. Enthalten sind hier neben Informationen
über das Gerät selbst (Hersteller, Gerät, Typenklasse, Möglichkeiten,
Waitstates, Interrupt, ...) auch die benötigten Speicherbereiche.
Damit ist es dem BIOS möglich, die Karte korrekt ins System einzubinden,
ohne daß Ressourcenkonflikte auftreten oder sich der Benutzer mit
DIPSchaltern, Jumpern etc. herumschlagen muß.
Am Macintosh-Sektor (NuBus) und am Amiga-Sektor (Zorro II/III-Bus) ist
z.B. das Problem der Autokonfigurierung übrigens bereits seit der
Existenz der jeweiligen Bussysteme (also seit über 10 Jahren) gelöst!
Der PCI-Standard sieht mittlerweile auch optional die "Hot-Plug-Fähigkeit"
vor, so daß PCI-Karten sogar im Betrieb gewechselt werden können.
Das darf aber in keinem Fall am Hades oder Milan gemacht werden, da dies
zur Zerstörung des Mainboards oder der Karte führen kann (für
dieses Feature sind spezielle Voraussetzungen erforderlich).
Quellenverzeichnis:
[1] PCI Local Bus Specification Revision 2.0
[2] Elrad 3/97 und 4/97 (Bus Basics - Technische Grundlagen des PCI-Bus)
[3] PCI Special Interest Group
P.O. Box 14070
OR 97214, Portland, USA
http://www.pcisig.com
[4] AMCC - http://www.amcc.com
[5] PLX Technology - http://www.plxtech.com
[6] Xilinx - http://www.xilinx.com
[7] Lattice Semiconductor - http://www.latticesemi.com
Milan-Homepage:
http://www.milan-computer.de
Milan-Newsletter bestellen/abbestellen:
http://www.milan-computer.de/html_d/letter.html
Letzte Änderung am 08. JuLi 1998, 13:07
© 1998 thomas
raukamp communications, alle Rechte vorbehalten
"Und umzuschaffen das Geschaffene, daß sich's nicht zum
Starren waffne, wirkt ewiges lebendiges Tun." (Goethe)
|