Back to Diane's HomePage
Kontakt Datenschutz

Diane's PDP-11 Page


English version


von

Diane Neisius

Aktualisiert: 15. September 2012



Inhalt

Warum eine DEC PDP-11/03? (1 Bild)

Alte Hardware flottgemacht (3 Bilder)

Minimalsystem testen (1 Bild)

Alte Floppy emuliert (veraltet, 1 Bild) +++NEWSFLASH 2013+++

Altes Tape emuliert (1 Bild. 1 Screenshot, 1 Graphik) NEU

Toolchain für Kernel-Bau (1 Screenshot)

Am Ende doch noch... UNIX! AKTUALISIERT

Anhang: PDP11 mit PC Netzteil betreiben (2 Graphiken)

Links

WIRD FORTGESETZT!




Warum eine DEC PDP-11/03?

Computer-Oldies besitze ich eine ganze Reihe. Eigentlich sammele ich 68000er der 1980er Jahre, aber es gibt soviele Seiten über Amigas, Atari STs, Sinclair QLs und Apple Macs, daß ich nicht auch noch eine zu machen brauche. Immerhin hat die Architektur der PDP-11 die Entwicklung der MC68000- Prozessoren so massiv beeinflußt, daß eine PDP durchaus Ehrenmitglied in meinem "Club 68k" werden darf.
Das erste Mal begnegnet bin ich einer PDP-11 zu Beginn meines Studiums. Programmierpraktika wurden auf der 11/34 des Institutes durchgeführt, hier hatte ich zuerst Berührung mit Unix, Assembler und C. Das ist wahrscheinlich vielen Studenten meiner Altersgruppe so gegangen und vermutlich mit dafür verantwortlich, daß Unix-Clones wie Linux sich bei Leuten wie mir so großer Beliebtheit erfreuen.

Leider sind PDPs heutzutage nicht mehr so einfach aufzutreiben wie Amigas oder Ataris. Sind ja auch schon etwas älter. Immerhin hat frau bei der PDP-11/03 noch gewisse Chancen, die ist ab Mitte der 1970er massiv in Maschinensteuerungen verbaut worden. Heutzutage würde so etwas als "Embedded Controler" bezeichnet werden. 11/03s sind übrigens in der Industrie zum Teil heute noch, nach 30 Jahren, in besagten Maschinensteuerungen im Einsatz (ob die modernen Controler auch so lange durchhalten?).
Darin liegt die Chance, an Teile zu kommen - sie tauchen gelegentlich als Elektronikschrott auf, und wer bereit ist, etwas tiefer in die Tasche zu greifen, ergattert die eine oder andere Platine noch bei einem der Händler, die Gebrauchtes als Ersatzteile einlagern.
Wem das zu teuer ist oder wer sich nicht den Griff zum Lötkolben zutraut - dann gibt es noch den SIMH Emulator (siehe Links), der unter vielen berühmten Computer-Oldies auch die PDP-11 in zahlreichen Varianten emuliert. Mit SIMH habe ich so aus Spaß wieder ein Unix V5 auf einer emulierten 11/45 und ein RT-11 V4 auf einer emulierten 11/03 mit RX01 Floppy zum Laufen bekommen.

Bild 1 - Mein erstes Stück echte PDP-11 Hardware war dieser Microcode-ROM des LSI-11 Chipsatzes. Er ist zugleich das älteste, denn das Herstellungsdatum ist Mitte 1977. Stammt aus dem Elektronik-Schrotthandel - und funktioniert noch trotz einer kleinen Macke im Keramikgehäuse.

Technisch ist die ab 1975 gebaute PDP-11/03 übrigens deswegen interessanter als neuere Modelle, weil sie vom logischen Aufbau stärker als andere der ersten PDP-11, der 11/20 von 1970, gleicht. Der Prozessor ist zwar nicht mehr aus diskreten Bausteinen aufgebaut, sondern besteht aus 4 oder 5 hochintegrierten Chips, aber das Fehlen der MMU, die Begrenzung des Adreßraumes auf 16 Bit und die Floating-Point Befehlsatzerweiterungen des Hauptprozessors statt eines zusätzlichen FP-Coprozessors sprechen eine deutliche Sprache.
Über die kleine 11/03 gibt es nicht soviele Informationen im Web. Eine Menge Fans der PDP-11 haben einen der großen alten Klassiker, eine PDP-11/44 oder /45 vor dem Schrott gerettet und betreiben sie sowie ihre Webseiten mit großem Enthusiasmus (siehe Links). Auch die eine oder andere 11/23 ist in so mancher Privatsammlung zu finden. Die PDP-11/03 taucht heutzutage, trotz ihrer großen Verbreitung in der Industrie, nicht so häufig auf. Deswegen halte ich meine Erfahrungen bei der Restaurierung auf dieser Seite fest.




Alte Hardware flottgemacht

Mein ursprünglicher Plan war, den Elektronik- Schrotthandel regelmäßig nach Chips des LSI-11 Chipsatzes zu durchkämmen, um so einen vollständigen Satz zusammenzubekommen. Da Adreß- und Datenbus gemultiplext sind, hätte sich mit ein paar meiner alten SRAM-Chips auf diese Weise vielleicht ein ähnlich primitiver Rechner wie die auf dem Intel 8008 basierende Mark-8 (Bauanleitung von 1971) zusammenlöten lassen. Bevor ich soweit kam, entdeckte ich die Qbus-Module und die Backplane, die ich jetzt benutze, habe aber trotzdem weitergesammelt - und verfüge jetzt über vier komplette Sätze LSI-11 Bausteine, die alle noch funktionieren! Nachfolgend eine kleine Tabelle, die einen Vergleich der Typennummern vornimmt (alle aufgeführten in meinem Besitz sind austauschbar):

LSI-11 Chip DEC Nr. Western Digital Nr. Prozessorfunktionen
1611H Data Chip 21-15579-00,   21-16890-00AB1611-A00interner Datenbus, ALU, Registersatz
2007C Control Chip23-002C4-00,   23-003C4-00AB1621-A07State Machine, Befehlsdecoder
3010D Microm 1 23-001B5-00,   23-008B5-00AC1631-A10Microcode für Standard- Befehlssatz Teil 1
3007D Microm 2 23-002B5-00,   23-007B5-00AC1631-A07Microcode für Standard- Befehlssatz Teil 2
3015D optional EIS/FIS23-003B5-00,  23-009B5-00AC1631-A15optionaler Microcode für "Extended Instruction Set"- und "Floating-point Instruction Set"- Befehle

Bild 2 - Dies sind die Qbus-Module, die ich 2009 als funktionstüchtige Einzelteile ergattert habe. Von links nach rechts:
M7270 LSI-11/2 CPU (der optionale EIS/FIS- Microm fehlte ursprünglich, ist hier aber schon eingesetzt),
M8044 MSV11-D 64 kByte RAM,
M8017 DLV11-E serielles Interface; später gesellte sich dann noch ein
M7946 RXV11 Floppy Interface hinzu (ganz rechts).
Vorn die Backplane, ein H9281-BA mit vier doppelten Steckplätzen. An den Schraubanschlüssen ist hier schon ein PC- Netzteil- kompatibler Stecker angebracht.

Der Zusammenbau der Platinen ist dank ihrer Modularität nicht problematisch. Grundregel Nummer 1: die CPU steckt immer am Anfang der Backplane (so daß die Chips vorne sichtbar sind, bei meiner Backplane ist das die Seite mit den Stromanschlüssen). Grundregel Nummer 2: es darf keine Lücken zwischen den Platinen geben. Für den ersten Test habe ich also von vorn nach hinten CPU, RAM, serielle Schnittstelle eingesteckt und den letzten Steckplatz freigelassen.
Ein bißchen muß frau noch basteln, ehe diese absolute Minimal- Konfiguration einer PDP-11 Lebenszeichen von sich gibt. Die Stromversorgung kommt, wie schon erwähnt, aus einem alten PC-Netzteil. Die LSI-11 CPU möchte allerdings einen bestimmten Einschaltzyklus haben, deswegen ist noch eine kleine externe Platine notwendig, die auf den 10-pinnigen Anschluß der Backplane gesteckt werden muß. Der Schaltplan stammt in seinen Grundzügen aus dem PDP-11/03 Manual von DEC [1]. Dort ist auch die Belegung des Anschlusses an der Backplane zu entnehmen.

Bild 3 - Meine kleine Kontrollplatine mit je drei Schaltern und Anzeigedioden. Absolutes Minimum wären ein Schalter, der "HALT" auf Masse legt, und ein (entprellter!) Schalter, der "DC OK" auf logisch High legt. Der dritte Schalter auf der Platine ist optional für die Line Time Clock. Die LEDs sind eher Luxus, meine zeigen Netzteil- Power, das "SRUN"- Signal und "HALT" an. Die TTL-Chips besorgen das Entprellen der Schalter.

Bild 4 - Noch eine Kleinigkeit fehlt, damit die 11/03 mit mir kommunizieren kann: der proprietäre DEC- Stecker an der Platine muß in einen seriellen Standard- Anschluß überführt werden. Das besorgt dieses kleine Patchboard. Es werden nur drei Leitungen gebraucht, RxD, TxD und Masse. Ich habe sie auf einen Anschluß geführt, wie er auch auf PC-Motherboards verwendet wird, um ein Standardkabel verwenden zu können.

Die Konfiguration der Seriellschnittstelle ist nicht ganz unproblematisch, sofern man nicht eine der alten erwischt hat, die schon als "console terminal" vorkonfiguriert sind. Letztere muß zwingend den I/O-Port an der (oktalen) Adresse 177560 haben und den Interrupt- Vektor 60 benutzen. Auf den meisten Platinen läßt sich das über Jumper einstellen, die verschiedenen Platinenrevisionen stimmen aber meist nicht überein - hier ist Detektivarbeit im Internet gefordert, um das passende Manual herunterzuladen. Meine Seriellschnittstelle zum Beispiel war eine neuere Revision namens DLVE1, die in der PDP-11/23 und manchen VAXen mit Qbus- Schnittstelle als Modem eingesetzt wurde, logisch aber mit der DLV11-E identisch ist. Es dauerte eine Weile, ehe ich dahinterkam.
Zusätzliche Schwierigkeiten machten die "Wire-Wrap"- Jumper - Werkzeug dafür ist heutzutage nicht mehr aufzutreiben. Glücklicherweise sind die Pins aber im Rastermaß angeordnet, so daß sich aus einer normalen Sockelleiste Steckjumper geeigneter Breite improvisieren lassen.
Wenn frau schon mal am Jumpern ist, nicht vergessen: heutzutage ist der quasi-Standard für serielle Schnittstellen (die an PCs sind fast immer so voreingestellt): 9600 Baud, 8 Bit, keine Parität, 1 Stoppbit, kein Handshaking.

Nach dem 2012er Debakel mit dem Floppy-Emulator habe ich mir grundsätzliche Gedanken dazu gemacht, welche Schnittstellen heutzutage noch Sinn machen. Nach den Erfahrungen, die andere Leute und ich gesammelt haben, ist bei alten Computern das Silizium selbst nahezu unverwüstlich. Ein paar Mal wurde ich angeschrieben, weil Leute einen Ersatz für das DEC-Netzteil suchten und offenbar aus meiner Beschreibung der Adapterplatine nicht schlau wurden. Die meisten Rechner fliegen auf den Schrott, weil die externen Speichermedien (Festplatten) schlapp machen. Controller für Laufwerke machen also - auch wegen der Probleme mit der Emulation - keinen Sinn.
Es gibt eigentlich nur eine Schnittstelle, die bei beiden Architekturen (alte '11 vs. moderner PC) noch aktiv unterstützt wird: RS-232. Seriell-Karten gibt es für Qbus zuhauf, und die Seriell-USB Umsetzer für PCs funktionieren unter allen Betriebssystemen recht problemlos. Und da es für die alten DEC-Rechner einen Massenspeicher gibt, der über eine Seriellschnittstelle angeschlossen wird (das TU-58 Bandlaufwerk), haben sich in der Zwischenzeit eine ganze Reihe von Emulatoren für den PC gefunden. Es ist mehrfach demonstriert worden, daß sich auf diese Weise sogar ein Betriebssystem booten läßt, namentlich XXDP und RT-11.
Das ist natürlich langsam. Aber schließlich sind die alten Schätzchen heutzutage kein echtes Arbeitsgerät mehr. Zeit sollte also nicht so eine Rolle spielen.




Minimalsystem testen

Zum ersten Test sollte natürlich die Spannungsversorgung sichergestellt sein - kein Problem, falls ein modernes PC-Netzteil verwendet wird. Ältere Originale sollten dagegen geprüft werden. Weiterhin bedarf es eines zweiten (moderneren) Rechners, auf dem ein Terminal- Emulator läuft - kaum jemand von uns dürfte wohl noch ein echtes altes Terminal besitzen. Natürlich muß der Rechner mit dem Terminal- Emulator über ein Nullmodem- Kabel mit der 11/03 verbunden sein.
Vor dem Einschalten des Netzteiles werden beide Schalter an der Kontrollplatine auf "offen/aus" gestellt. Netzteil anschalten, dann "HALT" schließen und dann "DC OK" einschalten. Als Antwort sollte der Terminal- Emulator etwas wie
000000
@
ausgeben. Wir befinden uns jetzt im sogenannten ODT (Octal Debugging Technique), dem Hardware- Debugger, der im Microcode der CPU eingebaut ist. Er ist gewissermaßen eine moderne Variante der Tasten und Lampen, mit denen sich die alten Großrechner der 1960er und 1970er Jahre auf ihrem Frontpanel schmückten. Es ist damit möglich, Speicherstellen und Register zu testen bzw. zu ändern, kurze Programmcodes einzutippen oder auch Urladeprogramme einzulesen (für diejenigen, die noch einen Lochstreifenleser auftreiben können). Der Prozessor selbst arbeitet in diesem Moment kein Programm ab, d.h. sein Programmzähler steht. Modernere Computer besitzen einen solchen Modus nicht mehr.
ODT ist etwas kryptisch zu bedienen. Er wartet nicht, bis die "Return"- Taste eine Zeile abschließt, sondern beäugt jedes getippte Zeichen mißtrauisch. Jede Ziffer außerhalb des oktalen Bereiches 0-7 wird mit einem "?" als Fehlermeldung quittiert. Um Speicherstellen anzusehen und zu ändern, tippt frau die oktale Adresse ein, gefolgt von "/". ODT gibt dann in derselben Zeile den Inhalt der Speicherzelle aus und wartet auf die Eingabe weiterer Ziffern - den neuen Wert der Speicherzelle. Wird die Eingabe mit "Return" abgeschlossen, landet frau wieder bei dem "@"-Prompt. Ein "Linefeed" (moderne Tastaturen besitzen dafür keine eigene Taste mehr, aber "Control-j" tut's auch) hingegen zeigt gleich das darauffolgende Speicherwort an. Werden keine Ziffern eingegeben, bleibt der alte Wert erhalten. Statt oktaler Ziffer kann mit "R0" bis "R7" auch auf die Register des Prozessors zugegriffen werden.
Ein eingetipptes oktales Programm kann mit der Eingabe der Startadresse gefolgt von "G" (das muß ein großes g sein) gestartet werden. Zuvor sollte allerdings der "HALT"- Schalter geöffnet werden.

Bild 4 - Das erste Lebenszeichen meiner PDP-11/03 links hinten im Bild. Die LSI-11-Chips auf der Platine im ersten Steckplatz sind deutlich zu erkennen. Hinter dem Rahmen der Backplane lugt das PC-Netzteil hervor. Im Vordergrund der Notebook meiner Freundin, auf dem der Terminal- Emulator läuft.
Als ich diesen Test durchführte, war der optionale FIS/EIS- Microm noch nicht eingesetzt.

Die Webseite "Hints on testing a dead PDP-11" (siehe Links) gibt nützliche Tips, wie die Funktionen von Prozessor und Speicher getestet werden können. Das erste "Programm", daß ich ausprobiert habe, war oktal 5007 an Speicherstelle 0. Es ist ein "Clear PC" Befehl, d.h. der Programzähler wird auf 0 gesetzt, was eine Endlosschleife ergibt. Ein 777 (Branch -2) tut das Gleiche, kann aber auf jeder Stelle im Speicher platziert werden.
Wenn's komplexer als diese einfachen Ein-Wort- Programme wird, sollte allerdings ein Teil Initialisierungsarbeit erfolgen - unter Umständen gibt es sonst sehr irreführende Programmabbrüche. Bestimmte Fehlerbedingungen führen Traps (bestimmte festgelegte Interrupts) aus, deren Vektoren schon initialisiert sein sollten. Gleiches gilt für den Stackpointer. Z.B. wird beim Versuch, einen nicht existenten Befehlscode auszuführen, ein "Illegal Opcode" initiiert - Programmzähler und Statuswort werden auf dem Stack gesichert, und der Prozessor holt sich den neuen Programmzähler von Adresse 10. Falls der Stackpointer aber uninitialisiert ist und irgendwo in einen nicht existenten Speicherbereich zeigt, löst der Versuch, PC und PS zu sichern aber vorher einen "Bus Error" aus - was sehr hinderlich bei der Fehlersuche sein kann.
Der Prozessor wird stets dann stoppen, wenn er den Befehlscode 0 (Halt) einliest. Normalerweise ist das der letzte Befehl eines kurzen oktalen Programmes, mit dem die Kontrolle wieder an ODT übergeben wird. Leere uninitialisierte Speicherzellen enthalten oft genug jedoch auch Nullen - ein Sprung ins Nirgendwo, beispielsweise durch einen uninitialisierten Trapvektor, wird also auch zu einem Stop führen. (Verlassen würde ich mich da aber nicht drauf!) Mein Trick ist nun, den Programmzähler eines Traps auf die Adresse des Traps minus 2 zu setzen und in diese 0 zu laden. ODT gibt dann genau die Adresse des Traps aus, der aufgetreten ist.
Das funktioniert jedoch nur dann, wenn der Stack in einem existenten Speicherbereich liegt. Also: SP (das ist R6) zum Beispiel auf 700 setzen. Für kurze Programme reicht das meistens. Ab 1000 oktal können dann Programme eingetippt werden (der Stack wächst nach unten, d.h. zu kleineren Adressen hin).
Folglich ist das also meine Startkonfiguration:

000000 / 000000
000002 / 000000
000004 / 000002		<--- bus error
000006 / 000000
000010 / 000006		<--- illegal instruction
000012 / 000000
000014 / 000012		<--- T bit trap
und dazu kommt noch für Floating point:
000242 / 000000
000244 / 000242
und die Initialisierung des SP:
R6 / 000700
und damit kann es dann losgehen, zum Beispiel mit einem Speichertest- Programm (nach dem Abbruch mit einem Bus Error Trap steht die Adresse der ersten nicht mehr existierenden Speicherzelle plus 2 in R0 und kann mit "R0 /" ausgelesen werden):
001000 / 005000
001002 / 005720
001004 / 000776
001006 / 000000
Auf ähnliche Weise können die FIS/EIS- Erweiterungen getestet werden. Falls der Microm nicht vorhanden bzw. kaputt ist, werden die entsprechenden Befehlscodes einen "Illegal Instruction" oder "Floating Point" Trap auslösen. Sonst läuft das Programm weiter, wie bei diesem FIS-Befehl "Fadd (R1)" in einer Endlosschleife:
001000 / 075001
001002 / 000776
Eine Endlosschleife kann übrigens jederzeit durch Schließen des "HALT"- Schalters abgebrochen werden. Bei obigem Beispiel ist es außerdem wichtig, R1 vorher auf irgendeinen Wert im Speicher zeigen zu lassen, etwa mit "R1 / 002000". Sonst gibt es wieder mal einen irreführenden Bus Error.
Dasselbe geht auch mit einem EIS-Befehl, zum Beispiel 070202 (Mul R2,R2), und dafür braucht R2 nicht mal mit irgendeinem sinnvollen Wert geladen sein.




Alte Floppy emuliert

NEWSFLASH: am 16.6.2013 hab ich das wieder zum Laufen bekommen. In Kürze gibt es Details. Hardware: Pentium III 650MHz, 100MHz FSB, 440BX Northbridge, PIIXE Southbridge, native Parallelschnittstelle @IO 0x378, im Bios auf "ECP" konfiguriert. Software: Debian GNU/Linux 5.01 (DVD1 reicht zum Installieren), Kernel 2.6.26, rxm mit gcc 4.3 kompiliert.
RXM funktioniert nicht mit Debian 6.0, USB-Parallelport-Kabeln oder auch Parallelport-PCI-Karten auf neueren PCs.

Eine Reihe von Gründen hat mich bewogen, nicht mehr auf die Suche nach einem echten alten Diskettenlaufwerk zu suchen. Zum einen mögen ja 30 Jahre alte Chips noch gut funktionieren, was sie in der CPU und dem Speicher auch tun, 30 Jahre alte Mechanik ist mit Sicherheit schon etwas ausgenudelt. Zum anderen bedingt ein altes 8-Zoll- Laufwerk dann eben auch eine passende 8-Zoll Systemdiskette. Die in lauffähigem Zustand aufzutreiben ist mit Sicherheit nicht so einfach wie sich Images aus dem Internet zu ziehen. Beispielsweise ist die Erstellung eines bootfähigen Diskettenimages unter RT-11 auf dem SIMH- Emulator eine ziemlich einfache Fingerübung. Und nicht zuletzt hab ich ja schließlich auch kein echtes VT100- Terminal mehr hier rumstehen, sondern benutze einen Terminal- Emulator auf dem PC.

Eine Emulation des RX01- Diskettenlaufwerks für den PC mußte also her, und für diesen Zweck wird frau im Internet mit dem freien "rxm" Emulator von Charles Dickman fündig [siehe unter "Links"]. Rxm emuliert ein RX01/RX02- Laufwerk über den Parallelport des PC, dieser wird über eine kleine Adapterplatine mit dem Ausgang der Floppy-Interface- Karte in der PDP verbunden. Da rxm direkt auf die Hardwareadresse des Ports zugreift, muß der PC aber noch über eine "echte" Parallelschnittstelle verfügen - ein USB-zu- Parallel-Kabel tut's leider nicht.
Ich habe mir den Schaltplan heruntergeladen und mit ein paar kleinen Änderungen auf einer Lochrasterplatine zusammengelötet. Die Änderungen betreffen die NAND-Gatter, ich habe die 74LS38 bzw. 74LS00 durch einen einzelnen 74LS04 Hex-Inverter-Chip ersetzt (hatte ich gerade passend in meiner Bastelkiste). Die 180-Ohm- Widerstände habe ich alle weggelassen, ebenso einen Teil der 390-Ohm- Pulldown- Widerstände. Nur an den Leitungen RX_INIT, RX_RUN, RX_DATA, RX_DONE, RX_TRANSFER_REQUEST und RX_SHIFT habe ich sie belassen (aufgrund des "debuggings", das ich im folgenden noch beschreibe). Auf der Seite der Floppy- Karte in der 11/03 habe ich wieder in kleines Patchboard (ähnlich dem an der Seriell-Karte) eingefügt und dieses über ein vorkonfektioniertes 10-poliges Kabel mit dem Adapter verbunden.
Rxm habe ich mit gcc aus dem Source unter Debian Linux 5.0 übersetzt. Das Makefile zickte etwas, aber es war sehr einfach, die passende Zeile einfach herauszukopieren und an der Shell einzugeben. Da direkte Hardware-Zugriffe unter Linux für normale User verboten sind, muß das Binary als "root" gestartet werden. Praktischerweise wird das über Setuid erledigt (als root einloggen, "chown root rxm" und "chmod 4755 rxm" eingeben, und schon klappt's auch von dem normaler User-Account aus).
Bild 5 - die Adapter- Platine für den rxm- Emulator zwischen PDP-11 und PC gestöpselt. Die Backplane der 11/03 ist hier von der Seite zu sehen.
Zwischenzeitlich hab ich mir auch ein etwas kleineres Netzteil besorgt (100 Watt reichen aus), das später in das Gehäuse paßt. Es geht im Kabelgewirr unter dem Adapter etwas unter.

Für die ersten Tests startet frau rxm am besten im höchsten Verbose-Modus mit "rxm -vvv -t RX01". Leere Disk-Images werden automatisch erzeugt.
Am PDP-Terminal wurde zuerst das Vorhandensein der beiden Register des RXV11-Floppy- Interfaces getestet. Das Kontroll- Register RXCS findet sich an der Adresse (oktal) 177170, das Datenregister RXDB an Adresse 177172.
Allererster rxm-Test war ein Init-Kommando. Dazu schreibt frau oktal 40000 in das RXCS, was auf der PC-Seite mit der Ausgabe "RX_INIT request recieved" quittiert wird. An diesem Punkt funktionierte also wenigstens das Puffer- Flipflop auf der Platine schon mal. Ein erneutes Auslesen des RXCS lieferte oktal 000040, das "done"-Bit war also ordnungsgemäß gesetzt.
Nächster Test: ein Funktionskommando. In RXCS wurde oktal 11 geschrieben (ein "NOP"). Das sollte auf dem PC eine "RX_RUN request recieved" Meldung und die Angabe des Funktionscodes, sowie ob es sich um einen 8-Bit oder 12-Bit Code handelt, erzeugen (RXV11 kann nur 8-Bit-Codes). Bei mir klappte das zuerst nicht und führte dazu, daß ich nach und nach die o.a. Widerstände aus- und umgelötet habe. Falls alles klappt, sollte ein erneutes Auslesen des RXCS wieder 000040 "done" liefern.
Auf diese Weise lassen sich die Tests stückweise steigern. Ein Funktionscode 7 (das ist ein "read sector") in RXCS geschrieben sollte einen "transfer request" auslösen (RXCS zeigt beim Auslesen oktal 000200). Nun kann in RXDB die Sektornummer (1-26 dezimal) geschrieben werden, letzeres wiederholt sich noch einmal für die Tracknummer (0-76). Auf diese Weise können alle die Funktionscodes von Hand getestet werden, die im Manual [6,7] beschrieben sind. Bei einigen ist das etwas mühselig, weil der Inhalt des Sektor-Puffers Byte für Byte durch RXDB geschleust wird, es lassen sich auf diese Weise aber schon Testmuster auf dem Disk-Image speichern. (Letzeres läßt sich mit dem "od" Kommando von der Shell aus überprüfen.)
Der letzte Test, den ich gemacht habe, war den Bootcode in die 11/03 einzutippen, der in [7] und anderen Manuals abgedruckt ist. Erwartungsgemäß wurde der erste Sektor nach Adresse 0 geladen, und dort blieb der Prozessor stehen, weil ja nur 128 Nullen von dem leeren Disk-Image geladen worden waren.
Immerhin war damit die Funktionstüchtigkeit des Emulators erwiesen. Jedenfalls war das 2009 so, 2012 funktionierte das dann nicht mehr.




Altes Tape emuliert

PDP-11en sind in ihrer Zeit gelegentlich mit TU-58 Bandlaufwerken betrieben worden. Diese Bandlaufwerke hatten relativ wenig Speicherplatz (256k), waren ziemlich langsam, hatten aber den großen Vorteil, daß sie keinen speziellen Controller brauchten. TU-58 Bandlaufwerke wurden über eine gewöhnliche Seriellschnittstelle angeschlossen. Das bedeutet für uns heute, daß man keine spezielle Hardware löten muß, sondern ein gewöhnliches Nullmodemkabel zwischen der PDP und dem PC mit dem Emulator genügt.
Moderne PCs haben heutzutage in der Regel keine seriellen Schnittstellen mehr. Doch die handelsüblichen USB-Seriell-Kabel werden von allen gängigen Betriebssystemen gut unterstützt (für mich Linux). Ich verwende zwei dieser Kabel, die vom Linux-Kernel automatisch als /dev/ttyUSB0 und /dev/ttyUSB1 erkannt werden. Ich verwende /dev/ttyUSB0 für die Konsole und /dev/ttyUSB1 für die TU-58 Emulation.
Da diese Schnittstellen gut unterstützt werden, und damit zu rechnen ist, daß USB-Ports noch die nächsten Jahre Standard an den PCs bleiben werden, ist zumindest hardwareseitig nicht so ein Problem wie bei der Floppy-Emulation zu erwarten.
Bild 6 - Die 4-fach Seriellkarte DLV11-J gab es relativ preiswert in der ElektroBucht. Allerdings mußte ich so ziemlich jeden Jumper umkonfigurieren, wie hier an den roten Stellen zu sehen ist. Einige mußte ich sogar löten. Ich habe alle 4 Schnittstellen zurück in die Standardkonfiguration versetzt, Ausgabe an RS-232, 9600 Baud, 8 Bit, keine Parity, 1 Stopbit, IO Port 176500 (oktal), Interrupt Vektor 300 (oktal), Port 3 wird als Konsole verwendet (Port 177560, Vektor 60).
Nachdem alle Jumper neu gesetzt waren, funktionierte die Karte auf allen Ports tadellos.

Das Pinout der Seriellschnittstellen läßt sich ziemlich einfach in das eines DB-9 Steckers überfüren. Man braucht nur die drei Leitungen RxD, TxD und Masse (ground). Stecker und 10-polige doppelreihige Sockelleisten im 2.54mm-Raster gibt es bei den üblichen Elektronikhändlern. Als Kabel habe ich ein flexibles Mikrophonkabel verwendet, daß zwei Leitungen (für RxD, TxD) und eine Abschirmung (für Masse) besitzt.

Die allerersten Tests kann man gut wieder vom ODT aus machen. Man muß nur auf dem zweiten seriellen Port (bei mir /dev/ttyUSB1) ein zweites Terminalprogramm starten. Man kann dann auf dem ersten Terminal Testkommandos eingeben und die Reaktion im zweiten Terminal beobachten. Ist beispielsweise /dev/ttyUSB1 mit Port 0 der Karte in der PDP 11 verbunden, dann gibt eine Eingabe eines oktalen Wertes über die Konsole in die richtige IO-Adresse auf dem zweiten Terminal ein Zeichen aus:
176506 / 000102
gibt zum Beispiel ein "B" aus. Auf diese Weise kann man recht einfach die Portadressen auf Funktion abtesten.
Genauso einfach ist es, den Interruptvektor zu testen. Es braucht dafür auf der Seite der PDP ein kurzes oktales Programm:
1000 / 012700         <--- r0 = Reciever csr
1002 / 176500
1004 / 012760         <--- Setze im Rec. csr "interrupt enable"
1006 / 000100
1010 / 000000
1012 / 000777         <--- Endlosschleife
Natürlich muß auch hier, wie oben, vorher etwas im System aufgeräumt werden:
276 / 000000
300 / 000276
302 / 000000
304 / 000302

R6 / 000700
setzen auf die schon bekannte Weise einen Stack und die zum Port gehörigen Interruptvektoren. Startet man nun das kurze Programm mit 1000G, dann läuft die PDP solange in der Endlosschleife, bis man auf dem 2. Terminal eine Taste drückt. Das Programm bricht dann mit der Ausgabe 000300 ab und man ist wieder im ODT.
Ganz analog können die anderen Portadressen auf Funktion getestet werden. Port 1 liegt bei 176510, Vektor 310, Port 2 bei 176520, Vektor 320 (alles in oktal). Port 3 ist bei mir die Konsole,

Nachdem das Hardwarelayer funktioniert ist es Zeit, sich dem Emulator zuzuwenden. Ich habe den tu58em von ak6dn verwendet (siehe Links). Er baut unter Linux problemlos. Bei der Ausführung gibt es jedoch ein Problem: die Definitionen im Systemheader termios.h scheinen nicht ganz einheitlich zu sein. Auf meinem System (Debian GNU/Linux 6.0) wird beim Start von tu58em die Baudrate nicht richtig gesetzt. Es gibt jedoch einen einfachen Workaround dafür: einfach NACH dem Start des Emulators auf einer zweiten Shell mit "stty -F/dev/ttyUSB1 9600" die Baudrate manuell setzen, dann geht es.
Screenshot - Hier ist ein einfacher manueller Test von tu58em zu sehen. Die Konsole (an /dev/ttyUSB0) ist im schwarz-grünen Xterm zu sehen, ganz stilecht wie in den 1970ern. :)
Unten liegt die Shell, in der auf Port 0 (an /dev/ttyUSB1) der TU-58 Emulator läuft, hier gestartet mit "tu58em -v -d -p /dev/ttyUSB1 -c zero.tap", was ein leeres Band mit Nullen emuliert und reichlich Diagnoseinformationen rausrückt.
Hinter dem Fenster mit dem tu58em ist die zweite Shell zu sehen, mit der nach dem Start des Emulators die Baudrate nachträglich gesetzt wurde.

Mit ODT auf der Konsole kann man nun dem Emulator ein paar Kommandos vorsetzen. Im Xterm ist zu sehen, wie ich nacheinander in Port 176506 die oktalen Werte 4 (init), 4 (init), 10 (boot) und 0 (Bandlaufwerk 0) eingegeben habe. Unten sind die Reaktionen des Emulators zu sehen: Auf ein zweimaliges init hin antwortet er mit einem "cont", und auf die Folge boot 0 hin beginnt er mit der Übertragung der 512 Bytes von Block 0 des Bandes.

Natürlich läßt sich auf diese Weise ein einfacher Bootloader zusammenstellen. Man findet im Web relativ häufig den aus dem TU-58 Technical Manual zitiert, der bei mir aber nicht funktioniert hat (tu58em erkannte eine "Null" und dann blieb alles stehen). Den Loader aus dem ROM abzutippen war mir zu mühsam (und rechtlich zu fragwürdig). Ich hab deshalb einen einfachen eigenen gebastelt (der Quelltext für den pdp11-aout-as Crossassembler findet sich hier):

1000 / 005000     <--- r0 = 0               (bootloader standard)
1002 / 012701     <--- r1 = reciever csr    (bootloader standard)
1004 / 176500
1006 / 012702     <--- r2 = transmitter csr (bootloader standard)
1010 / 176504 
1012 / 012761     <--- sende "init" 
1014 / 000004 
1016 / 000006
1020 / 005761     <--- warte bis vollständig gesendet
1022 / 000004 
1024 / 001775 
1026 / 012761     <--- sende "init" 
1030 / 000004 
1032 / 000006 
1034 / 005761     <--- warte bis vollständig gesendet
1036 / 000004
1040 / 001775 
1042 / 012761     <--- sende "boot" 
1044 / 000010 
1046 / 000006 
1050 / 005761     <--- warte bis vollständig gesendet 
1052 / 000004 
1054 / 001775 
1056 / 012761     <--- sende 0 (Drive Nr.)
1060 / 000000 
1062 / 000006 
1064 / 005761     <--- warte bis vollständig gesendet 
1066 / 000004 
1070 / 001775 
1072 / 105711     <--- warte bis Zeichen vollständig empfangen	  
1074 / 001776 
1076 / 116105     <--- ...und weg damit (das war die "cont" Antwort)
1100 / 000002 
1102 / 005003     <--- r3 = 0 (Byte Zähler)
1104 / 105711     <--- warte bis Zeichen vollständig empfangen
1106 / 001776 
1110 / 116123     <--- schreibe es in den Speicher, erhöhe r3
1112 / 000002 
1114 / 022703     <--- r3 = 512?
1116 / 001000
1120 / 001371     <--- wenn nicht, dann weiter ...
1122 / 005007     <--- ... sonst springe in den Boot Block
Mit diesem kleinen Programm (ist übrigens hiermit GPL - have fun!) kann man nette Experimente machen. Ich habe damit Nullen (aus dem "zero.tap", s.o.) und Bytemuster aus anderen Dateien geladen - hängt nur davon ab, was man dem tu58em als Tape Image Datei gibt.
Im Netz geistern einige TU-58 Bandimages von alten Betriebssystemen herum, es gibt eine ganze Reihe davon für das Betriebssystem XXDP. Es ist allerdings nicht herauszubekommen, wer die Rechte daran hat (HP? Mentec?), oder ob es inzwischen "Abandonware" ist. Fast alle Freaks scheinen es zu benutzen, ohne sich über eine Lizenz Gedanken zu machen. Falls jemand etwas zu dem Thema weiß, würde ich mich über eine Mail freuen.
Denn ich bin mir sicher, daß XXDP auf meiner 11/03 vom tu58em aus auch booten würde, so wie bei vielen anderen Leuten.




Toolchain für den Kernel-Bau

Einführung
Wie ich oben schon erinnert habe, war in den 1980ern eine PDP-11 mit Unix drauf so ziemlich der Heilige Gral des Hackers. Heutzutage sind die alten Unix-Versionen für private nichtkommerzielle Nutzung frei. Also wollte ich das natürlich auch für meine 11 haben. Es gibt eine Version, die auf der 11/03 läuft: das sogenannte LSI-Unix oder LSX. Allerdings wußte ich das bis 2012 nicht und habe mich daher zunächst auf die Suche nach einem kleinen freien Unix-Klon gemacht.
Diese Sektion bleibt natürlich auch für den Bau des LSX Kernels mit der GCC-Toolchain gültig. In der aktuellen Version ist auch der unten berichtete Bug behoben (nach meinem Report an gcc Bugzilla). Die aktuellen Arbeiten am LSX-Kernel habe ich mit gcc 4.7.1 und den Binutils 2.22 gemacht. Bitte beachten: in der neuen Version gibt es das target pdp11-dec-bsd nicht mehr, stattdessen muß man für pdp11-aout bauen.

Xinu
Also [2009] auf die Suche nach freien Betriebssystemen. Unix wurde in den 1980ern einige Male geklont, als AT&T die Verwendung des Source-Codes für Ausbildungszwecke untersagte. GNU, Minix, Xinu und letztlich Linux sind auf diese Weise entstanden. Von diesen wollen alle außer Xinu auch eine MMU haben, fallen also wiederum aus.
Xinu ist detailiert im Buch von Comer [9] beschrieben, das nebenbei bemerkt eines der besten Bücher über Betriebssysteme ist, das ich kenne. Es wurde in der Urfassung für die PDP-11/03 geschrieben. Xinu selbst ist eher als Embedded-Betriebssystem realisiert, für File-Zugriffe hat es umfangreiche Netzwerk- Unterstützung. Letztere brauche ich nicht, weil ich keinen DEQNA- Adapter für meine 11 habe. Dafür hab ich ein lokal emuliertes RX01- Laufwerk, das zunächst nicht unterstützt wird. Kann aber nicht so schwer sein, dafür Treiber zu schreiben. Schließlich sind Übungsaufgaben dieser Art der ursprüngliche Zweck von Xinu.
In der letzten Version gehört auch eine Shell zu Xinu, die alle notwendigen Befehle für ein etwas User- Spielen schon enthält. Nebenbei bemerkt, ein bißchen erinnert mich das an die Zeit vor den Live-Linux- CDs, an meine Versuche mit einem Minimal- Linux, das von Diskette zu booten war und nur aus statisch compiliertem Kernel und der 'sash' Standalone-Shell bestand (beides zusammen paßte gerade so auf eine normale PC-Diskette).
Aber schließlich will ich ja auch nicht ernsthaft arbeiten mit meiner alten PDP-11, sondern nur ab und zu mal ein kleines Programm drauf laufen lassen. Da ist so ein halbes Embedded-System mit Crosscompiler auf dem Host schon ganz ok.
Der Xinu source tree war ursprünglich auch nur für die PDP-11 erhältlich und enthielt ein SDK in Form von Crosscompiler etc. (das ist heute anders), dieser Zweig wird heute aber nicht mehr gepflegt. Meine ersten Versuche gingen daher dahin, den Crosscompiler zu reanimieren. Da die alte SDK von Xinu auf einem VAX-Host unter 4.3 BSD laufen sollte, war das aussichtslos - die Unterschiede zu Linux sind dann bei allen gemeinsamen Wurzeln doch zu groß. Gerade einmal das 'nm11' wollte kompilieren, ob es auch lief, weiß ich nicht einmal.

GCC toolchain
Aber eigentlich brauchte ich ja auch nur die Sourcen von Xinu selbst. Einen Crosscompiler beschaffen ist auch aus anderen Quellen möglich. Der GNU C compiler kann z.B. als Crosscompiler gebaut werden, auch wenn das so seine Tücken hat. Es gibt dazu inzwischen aber eine Reihe sehr hilfreicher Webseiten, siehe Links.
Ich habe binutils-2.19.1 und gcc-core-4.3.3 verwendet. Beide mögen es nicht, wenn sie in ihren Quellverzeichnissen gebaut werden, also habe ich für jedes Paket ein Arbeitsverzeichnis erstellt und die Quellen dort in je ein Unterverzeichnis src/ entpackt. Binutils baut dann mit:
src/configure --target=pdp11-dec-bsd --disable-nls
make all
make install
(letzteres natürlich mit root-Rechten). Für gcc mußten auf meiner Debian-5.0- Installation noch die Bibliotheken libgmp und libmpfr mitsamt devel-Dateien nachinstalliert werden. Libmpfr-dev ist nicht auf der Debian-DVD dabei, die passende Version kann aber bei debian.org heruntergelagen werden.
Gcc baut dann wieder (in seinem eigen Arbeitsverzeichnis natürlich) mit:
src/configure --target=pdp11-dec-bsd --disable-nls --without-headers --enable-languages=c
make all-gcc
make install-gcc
(letzteres wieder als root). Ein kleineres Problem gibt es dabei mit der libgcc, die nicht bauen will (mit "make all-libgcc").
Das scheint ein Problem der Assembler-Ausgabe von gcc zu sein, defaultmäßig ist nämlich unix-asm eingestellt, der GNU Assembler aus den Binutils will aber dec-asm haben. Nennen Sie es Bug oder Feature, ich wollte jedenfalls nicht auch noch den gcc patchen (ist mir nun wirklich zu "nerdy"), sondern hab mir ohne libgcc geholfen (s.u.) und rufe gcc halt immer mit "-mdec-asm" auf, dann gibt es keine Probleme.
{Nachsatz: die 2009er Version gcc 4.3.3 übersetzte das logische UND "&" fälschlich in den Assemblerbefehl "BIC" (vgl. [8]). Ich hatte das über das gcc Bugzilla berichtet, und in der aktuellen Version gcc 4.7 ist das Problem behoben. Damals in 2009 hab ich mir einen Patch gebastelt, den ich aus historischen Gründen hier verlinkt lasse... den Patch für gcc 4.3.3 und eine Anleitung finden Sie hier. Wie gesagt, in der aktuellen Version von gcc wird er nicht mehr gebraucht.}

Alter Code und moderner Compiler
Die Sache mit der libgcc ist übrigens nicht so schlimm, wie es sich anhört. Jedenfalls nicht, wenn der Code für eine PDP-11 mit EIS/FIS- Erweiterung übersetzt wird, gcc gibt dafür nämlich sehr viel schon als nativen Code aus. Da der Xinu-Kernel ja schon getestet ist, sollte alles weitere notwendige sich in den Xinu-Library Sourcen befinden.
Lediglich 32-bit signed und 16-bit unsigned Division und Modulo werden als Funktionsaufrufe "___divsi3", "___modsi3", "___udivhi3" und "___umodhi3" vom Linker angemahnt, wenn versuchsweise die Xinu-Libraries libsa.a und libxc.a gebaut werden und dann auch das beiliegende Standalone- Binary des "demo"- Programmes gecrosslinkt wird. Für diese finden sich aber mit ldiv.s und lrem.s in den Libraries die passenden Funktionen, es bleibt also nur noch, mit ein paar Zeilen Assembler einen Wrapper für die libgcc- Aufrufe zu schreiben.
Dann wird nur noch "___main" vermißt, das frau getrost durch den Assemblerbefehl "rts pc" liefern kann - schließlich ist hier alles statisch, wir brauchen keine Konstruktoren.
Anfangs nicht benötigt wurde die unsigned long Divison und Modulo- Funktion - hier läßt sich aber aus dem Fundus des gcc-Source leicht die Funktion "udivmodsi4" ausborgen, der Vollständigkeit halber.
Float funktioniert leider überhaupt nicht, da gcc nur Code für die 11/40 FPU erzeugt - und da werden Variablen schon mal nicht initialisiert, dieser Code sieht nicht sehr vertrauenerweckend aus... weil auch die Option -mfis nicht funktionieren will, habe mir dann für die FIS-Befehle des LSI-11 Prozessors eine kleine Library libfis.a geschrieben, um mit float arbeiten zu können.
Übrigens geht es in die schlammigen Tiefen von prä-ANSI-C, wenn es ans Übersetzen geht. Da sind "=/" Operatoren zu finden (heute "/="), und um Funktionsprototypen scheint sich auch noch niemand gekümmert zu haben. Diese Kleinigkeiten lassen sich aber glücklicherweise leicht beheben.
Auch die Assembler- Syntax hat sich in den letzen 25 Jahren etwas geändert - normal geschriebene Zahlen werden heute als dezimal akzeptiert (nicht mehr mit einem Punkt am Ende), eine führende "0" weist auf oktal hin.

Runterladen des Binaries
Eigentlich ist das ganz einfach, wenn frau sich erinnert, daß die "11en" ganz früher über Seriell- Schnittstelle mit einem Fernschreibterminal (TTY) verbunden waren. Besagte Fernschreiber hatten nämlich häufig einen eingebauten Lochstreifenleser. Nach dem Start der PDP wurde also über die Konsolenschalter oder ODT ein kurzer Bootloader eingetippt, der dann den Binärcode vom Lochstreifen einlas. Das geht heute fast genauso, nach dem Eintippen muß dazu nur der Bootloader gestartet werden (mit dem ODT "G" Kommando, s.o.), über Shortcut der Terminal- Emulator beendet (bei minicom mit "Ctrl-A" und "Q"). Da nun der Bootloader der PDP-11 an der Seriellschnittstelle "horcht", wird das Binary einfach auf die Schnittstelle kopiert:
cp demo.bin /dev/ttyS0 
(soweit die notwendigen Zugriffsrechte auf /dev/ttyS0 gesetzt wurden).
Nun wird minicom wieder gestartet, der Bootloader mit der "Halt"-Taste an der 11/03 gestoppt, und dann kann mit dem ODT- "G"-Befehl das gerade geladene Programm gestartet werden.
Kurze Lochstreifen- Bootloader zum Abtippen finden sich im Web, ich habe meinen auf der YAPP (siehe Links) gefunden.
Er ist vielseitig einsetzbar, die Adresse, an der das Binary im Speicher der 11 starten soll, kann in 157766 eingesetzt werden (für gelinkte Xinu-Binaries immer 0). Nach dem Laden steht in 157752 die Anzahl der Bytes, die gelesen wurde, das ist eine nützliche Kontrolle. Der Wert kann auf dem Host z.B. mit "od demo.bin" überprüft werden, um sicherzustellen, daß die Übertragung vollständig war. Der Bootloader ist übrigens relozierbar, d.h. er kann in einen Speicherbereich eingetippt werden, der nicht überschrieben wird, dann ist er nach Löschen von 157752 (oder dem Äquivalent im Speicher) wiederverwendbar.
157744 / 016701
157746 / 000026
157750 / 012702
157752 / 000000    <-- offset (counter)
157754 / 005211
157756 / 105711
157760 / 100376
157762 / 116162
157764 / 000002
157766 / 000000    <-- bank (RAM Start Adresse)
157770 / 005267
157772 / 177756
157774 / 000765
157776 / 177560


Debuggen mit ODT
Jetzt befindet sich also die Binärdatei im Speicher der 11, wird gestartet und - läuft natürlich nicht. Rudimentäres Debuggen geht mit dem ODT direkt an der PDP-Konsole, ist aber etwas mühselig. Immerhin hab ich damit in den Abgründen zwischen den Bits herausgefunden, daß die Xinu- Libraries andere Vorstellungen von den Stackframes hatten als der gcc. Das läßt sich in csv.s beheben, hier wird einfach in der Funktion csv an der richtigen Stelle 2 vom Stackpointer subtrahiert. Dann funktioniert die Sache mit den lokalen Variablen jedenfalls schon mal.
Eine andere Sache betrifft den Zugriff auf Hardware- Adressen, bei denen Statusregister abgefragt werden. Gcc optimiert hier gerne scheinbare Leerschleifen weg, wenn die entsprechenden Variablen nicht als "volatile" deklariert werden.
Schlußendlich bekam ich das demo.c Programm zusammen mit libsa.a aber wirklich zum laufen auf der Hardware meiner PDP-11/03. Damit habe ich also schon mal eine funktionierende Toolchain, was ein wesentlicher Schritt vorwärts ist.
Bild 6 - Sieht nicht nach viel aus, die Ausgabe von "Hello World" und ein paar Zahlen, hat es aber in sich. Immerhin läuft hier formatierte Ausgabe mit printf(), das doch eine recht komplexe Funktion innerhalb der C-Library ist.




Am Ende doch noch... UNIX!

Einführung
In meinem Urlaub im Jahr 2012 bin ich beim Stöbern im Web doch noch auf eine Unix-Variante für die PDP 11/03 gestoßen: LSX (abgekürzt für "LSI-UNIX"). Diese Variante ist eine nochmals verkleinerte Version von Mini-Unix, das eine Anpassung von Unix V6 an Maschinen ohne MMU ist. Während Mini-Unix zwar ohne MMU auskommt und maximal vier Benutzer versorgen kann, aber dennoch eine RK05 Festplatte braucht, paßt LSX für nur einen Benutzer auf zwei RX01-Disketten (-images), kommt mit nur 40kB RAM aus und braucht natürlich auch keine MMU. Dennoch ist es ein komplettes Betriebssystem einschließlich C-Entwicklungsumgebung. Eigentlich mehr als das also, was ich gesucht habe. Nach 30 Jahren der Heilige Gral, endlich zum Greifen nahe!!! :)
LSX wurde 1975 entwickelt, hat aber (warum auch immer) die Bell Labs nie verlassen und war, bis 2004 bei einem Vintage Computer Treffen zwei Disketten damit auftauchten, einfach verschollen. 2006 hat Leonid Broukhis die geretteten Images davon dann wieder zum Laufen bekommen.
Wenn die Geschichte nur etwas anders verlaufen wäre, hätten wir schon seit 1976 einen Unix "11/x" PC haben können. Und die "x86" Rechner mit Windws wären uns erspart geblieben (aber leider auch Linux). Und niemand wüßte, wer um alles in der Welt Steve Jobs oder Bill Gates sind...
Wegen der Ableitung von Unix V6 fällt LSX natürlich auch unter die Ancient Unix License; darüber hinaus hat Mr. Lycklama, der ursprüngliche Autor der Patches, seine Änderungen der PDP Unix Preservation Society zur Verfügung gestellt. Es ist - nach dem gegenwärtigen Stand der Dinge - für private nichtkommerzielle Nutzung also frei.
Herunterladen kann man die LSX-Diskettenimages (inklusive C-Compiler und Sources) auf Leonid Broukhis's LSX Unix Restoration page [10] (siehe Links). Dort ist auch beschrieben, wie man LSX mit dem SIMH PDP-11 Emulator zum Laufen bekommt.
Ein Hinweis von mir: LSX erwartet defaultmäßig Großbuchstaben als Eingabe. Am Bootprompt also nicht "lsx" eintippen, sondern "LSX", sonst gibts einen HALT.
Dokumentation ist spärlich gesät. Man muß sich an die Unix V6 Doku halten (es gibt unter LSX halt sehr viele Dinge nicht). Ein Paper über LSX existiert [11] und ein internes Memo über das verwandte Mini-Unix [12], die über die speziellen Eigenheiten von LSX und die Anpassungen an einigen seiner Programme Auskunft geben (beide siehe Links).

Konzept
Ich habe darüber nachgedacht, welche anderen Schnittstellen sich zum Anbinden von Massenspeicher an den LSX-Kernel eignen würden, da die RX01 Floppyemulation nicht mehr zur Verfügung steht. TU-58 über serielle Schnittstelle wäre ein Ausweg. Man muß nur einen Treiber auf LSX portieren (es gibt einen in 4.2BSD Unix). TU-58 Emulatoren gibt es eine ganze Reihe, die sogar mit Erfolg zum Booten von PDPs eingesetzt werden.
Ein TU-58 Band hat genausoviel Platz wie eine RX01 Diskette: 256kB. Ein Rootfilesystem von LSX würde also draufpassen. Die ganze "schmutzige" Arbeit der Vorbereitung eines Filesystemimages kann mit SIMH erledigt werden.
Die Diskettenimages von SIMH sind allerdings 1:1 Sektorkopien einer ganzen Diskette, und zwar mit Interleave von 3. Zwar läßt sich das für ein TU58-Bandimage einfach konvertieren, und das Image sieht danach auch gut aus: Super Block, Inode Liste und Root Directory sind da, wo sie sein sollen, das läßt sich einfach mit od überprüfen (ich hab während meines Studiums damals mal gelernt, wie ein Unix Filesystem aussehen muß). Allerdings ist der Interleave-Faktor auch in den Bootloadern hardcodiert, so daß die sich mit einem TU58 Rootfilesystem nicht mehr verwenden lassen. Es geht mit LSX also wieder so los wie 2009 mit dem Xinu-Kernel geplant. Kernel per Crosscompiler auf dem PC bauen, mit Lochstreifenbootloader über die Konsolenschnittstelle hochladen und das Filesystem dann über einen Emulator anhängen, diesmal halt über die andere serielle Schnittstelle.

LSX Kernel crosscompilieren
Bei der Anpassung der Kernel-Sourcen an die heute verwendeten Tools wie gcc sind die gleichen Probleme wie schon mit Xinu (s.o.) aufgetreten. Ich habe die Dateien nach und nach angepaßt. Der tu.c Treiber aus 4.3BSD brauchte schon mehr Zuwendung, bis er compilieren wollte, hier hat sich seit Unix v6 doch einges getan. Das Hauptproblem ist, daß der Code des Treibers sehr viel größer ist als der des Floppy-Treibers, den er ersetzt. Der Kernel baute zunächst mit einer Größe von 21.6 Kilobyte. Damit läßt sich der Anfang des Userspace bei oktal 40000 nicht mehr halten, und alle Programme des Dateisystems müssen neu gebaut werden.
Ich habe die Aufteilung 24k Kernel, 32k Userspace gewählt, weil heutzutage Speicher in den alten Qbus-Maschinen nicht mehr knapp ist. Damit blieb auch etwas Platz für ein paar Diagnosebotschaften im Kernel. Ich habe ein einfaches "printk()", das nur Text ausgeben kann, spendiert und damit Ausgabe von Meldungen während des Startvorganges und bei "panic()" Systemabbrüchen eingefügt. Das wird beim Debuggen sicher helfen.
Damit baut schon mal ein binäres Image des LSX Kernels auf dem PC.

Wird fortgesetzt!




Anhang: PDP11 mit PC Netzteil betreiben

Weil mich in den vergangenen Monaten so viele Anfragen (mehr oder weniger) verzweifelter PDP-11 Besitzer erreicht haben, denen das originale DEC-Netzteil abgeraucht ist, gebe ich hier jetzt etwas detailierter an, wie ein modernes PC-ATX Netzteil an die Backplane der '11 angeschlossen werden kann. Ich habe das so, wie es hier beschrieben ist, an meiner 11/03 durchgeführt, es sollte mindestens bei den anderen QBus-Maschinen genauso gehen.

Der erste Teil ist einfach. An der Backplane sind Schraubanschlüsse dran, neben denen der jeweilige Spannungswert steht. An PC-Netzteilen sind die farbcodiert, es gilt:

gelb +12V
rot +5V
schwarz Masse (GND)

Der Anschluß für -12V wird zum Betrieb der PDP selbst nicht gebraucht (möglicherweise aber für Peripheriegeräte - schaut in eure Manuals!). Ich habe den vierpoligen "männlichen" Stecker von einem Festplatten-Stromversorgungs-Verlängerungskabel (gibt's bei den üblichen großen Elektronikhändlern) für den PC abgeschnitten, die Kabelenden abisoliert und an der Backplane angeschraubt.
Achtung: PC-Netzteile haben einen Interlock an der Anschlußleiste für die PC-Platine, das ist das grüne Kabel. Es muß mit Masse (schwarz) verbunden werden, damit das NT sich einschalten läßt.

Der zweite Teil betrifft den 10-poligen Stecker, der meistens neben den Schraubanschlüssen auf der Backplane sitzt. Einer der Pins fehlt, damit das Kabel nicht aus Versehen verkehrt angeschlossen werden kann. Diese Pins müssen beim Einschalten in einer bestimmten Reihenfolge geschaltet werden, damit die CPU losläuft.
Ich gebe hier nach den Daten im DEC-Manual [1] das absolute Minimum an, damit der kleine alte Schatz mindestens bis zum ODT kommt. Abhängig von der Konfiguration und Version der jeweiligen PDP-11 wird damit möglicherweise auch ein Systemstart möglich sein.

Die Pins des 10-poligen Steckers:

BDCOK der wichtigste Pin. Nachdem vom Netzteil eine stabile Spannungsversorgung kommt, wird dieser Pin auf logisch "1" gezogen (Bussignal Standard +3.4V, absolutes Minimum lt. Manual +1.7V) Dieses Signal MUSS entprellt sein.
BHALT Wenn dieses Signal auf logisch '0" (0V, GND) gezogen wird, bleibt der Prozessor stehen und geht in den ODT Modus. An der Konsole wird eine Oktalzahl und der @ Prompt ausgegeben.
BEVENT wenn dieses Signal auf logisch "0" gezogen wird, löst das in der CPU einen Interrupt aus. Kann in der Minimalkonfiguration unbeschaltet bleiben. Das DEC-NT versorgt hierüber die '11 mit der LTC (Line Time Clock, 50Hz/60Hz Timer-Interrupt, Rechtecksignal mit +3.4V). Manche Betriebssysteme werden ohne dieses Signal wahrscheinlich nicht starten.
BPOK kann unbeschaltet bleiben. Logisch ähnlich wie ein zweites BDCOK.
SRUN Rückmeldung von der '11, ob der Prozessor läuft. Kann man für die Ansteuerung einer LED verwenden. Wenn ich mich richtig erinnere, ist es invertiert (Prozessor läuft bei Ausgabe "0").
GND 0V Referenz (Masse).


Die Entprellung eines normalen Umschalters kann laut DEC-Manual mit Hilfe zweier Inverter geschehen (7404, 74LS04, 74HC04 oder wie immer die heute heißen). Im 7404-Baustein sind sechs davon vorhanden. Das resultierenende Ausgangssignal ist allerdings in 5V-Logik und muß noch auf die 3.4V-Buslogik der '11-Backplane angepaßt werden. Im allereinfachsten Fall kann das mit Hilfe eines Widerstandes geschehen, ich habe 47 Ohm in Reihe drin, das kann aber zuwenig sein. Ein vernünftiger Spannungsteiler oder noch besser ein Buskonverterbaustein 5V/3.3V wären viel besser. (Wenn das mal ein Mikroelektroniker nachmißt und mir die richtigen Werte mitteilt, wäre ich sehr dankbar.)
Update: Im Manual der 11/23 CPU, die ich kürzlich auf dem großen Internetflohmarkt aufgetrieben habe, steht dazu etwas. Die Busleitungen müssen mit 120 Ohm terminiert sein. Ich hab also bei mir 120 Ohm eingelötet, weil in der "aus" Stellung der Schalter auf Masse schließt. Funktioniert ohne Probleme.
Diese Entprellung ist für das BDCOK-Signal Pflicht, bei BHALT ist es nicht zwingend. Ich habe aber, da im 7404-Baustein ohnhein noch Inverter übrig waren, vorsichtshalber beide Schalter entprellt.

Einschaltvorgang:
1. BDCOK Schalter auf "aus", BHALT Schalter auf "an" oder "aus", je nachdem ob man in den ODT Modus will
2. Netzteil einschalten
3. BDCOK auf "ein", und dann sollte die '11 an sein und sich auf der Konsole in irgendeiner Form melden.

Das absolute Minimum für solche Tests sind nur drei Komponenten in der Backplane: CPU, Speicher (manchmal auf einer Platine) und die serielle Schnittstelle für die Konsole. Alle PDP-11 CPUs, die ODT unterstützen, sollten damit schon funktionieren. Ich empfehle das sehr für den ersten Test mit einem PC-NT, um bei einem möglichen Fehler den Schaden zu minimieren.

=== NACHBAU AUF EIGENE GEFAHR! ICH GEHE DAVON AUS DASS IHR WISST WAS IHR DA TUT! ===





Links


PDP11.org -- Dedicated to preserving the history and legacy of the PDP-11 series of 16-bit minicomputers.

Wikipedia -- Die Wikipedia- Seite über die gute alte 11.

hampage.hu/pdp11 -- This page is intended as a tribute to one of the most famous computers: Digital Equipment Corporation's PDP-11 series.

bitsavers.org -- Bitsavers, ein reiches Reservoir an Software und Manuals alter Computer.

YAPP -- Yet another PDP page - enthält die "Hints on testing a dead PDP 11"

SIMH -- Der SIMH Emulator.

RXM -- Charles Dickman's RXM Emulator Seite.

Building gcc -- Seite über das Bauen von gcc als Crosscompiler.

LSX -- Leonid Broukhis' LSX Unix Restoration Webseite

Unix v6 man -- Online Unix V6 man pages

TU58 -- AK6DN's TU58 Emulator Seite.



*

Referenzen

[1] LSI-11, PDP-11/03 User's Manual. EK-LSI11-TM-002, Digital Equipment Corporation, Maynard, Massachuchets, 1975.

[2] M7270 LSI-11/2 Microcomputer Module User's Guide. Digital Equipment Corporation, Maynard, Massachuchets, 1976.

[3] MSV11-D, -E User's Manual. EK-MSV1D-OP-001, Digital Equipment Corporation, Maynard, Massachuchets, 1977.

[4] DLV11-E and DLV11-F Asynchronous Line Interface User's Manual. Digital Equipment Corporation, Maynard, Massachuchets, 1977.

[5] RX02 Floppy Disk System User's Guide. EK-RX02-UG-001, Digital Equipment Corporation, Maynard, Massachuchets.

[6] RX01/RX02 Pocket Service Guide. EK-RX02-UG-002, Digital Equipment Corporation, Maynard, Massachuchets.

[7] RX02 Floppy Disk System User Guide. EK-RX012-PS-001, Digital Equipment Corporation, Maynard, Massachuchets.

[8] Rapid Recall LSI-11, PDP-11/03, LSI-11/2 Reference Card

[9] Comer, D.: Operating System Design: the Xinu Approach, Prentice Hall 1984.

[10] Broukhis, L.: LSX Unix Restauration. http://www.mailcom.com/lsx/

[11] Lycklama, H.: UNIX on a Microprocessor. http://www.alcatel-lucent.com/bstj/vol57-1978/articles/bstj57-6-2087.pdf

[12] Lycklama, H.: Memo on Mini-Unix (Bell Labs, internal). https://www.msu.edu/~mrr/mycomp/terak/termubel.htm




Created: 18.Apr.2009
© 2009 Diane Neisius