Weder TOS selbst, noch die TOS-kompatiblen Betriebssysteme bieten von sich aus die Möglichkeit zur direkten Kommunikation mit SCSI-Peripheriegeräten.
Zwar sind die meisten Ataris mit SCSI-Peripherie ausgestattet, aber jedes Gerät wird in der Regel über einen speziellen Treiber angesprochen. Jeder dieser Treiber enthält im Kern ähnliche Routinen zur Ansteuerung der SCSI-Schnittstelle von TT und Falcon oder der ACSI-Schnittstelle des ST. Universell nutzbar ist keiner dieser Treiber. Solange die am Atari betriebenen Peripheriegeräte überwiegend Festplatten waren, spielte dieses Thema keine besondere Rolle. Bei den von Atari verkauften Platten und später auch beim MegaSTE, TT und Falcon lag stets AHDI als Festplattentreiber bei. Wem AHDI zu langsam und altbacken ist, stehen schon lange leistungsfähigere und besser gepflegte Treiber zur Verfügung. CBHD, HuSHI, ICDBOOT und HDDRIVER dürften die bekanntesten Festplattentreiber für Ataris sein. Daß AHDI dagegen schon lange nicht mehr weiterentwickelt wird, stellt gewiß keine Neuigkeit mehr dar. Für aktuelle Festplatten ist AHDI ohnehin ungeeignet, da er am SCSI-Bus lediglich Platten bis zu einer Kapazität von maximal einem GByte unterstützt. Platten mit einer solch geringen Kapazität werden inzwischen aber kaum noch hergestellt. Neue Platten kommen in aller Regel mit einer Kapazität von mindestens zwei GByte daher, Tendenz steigend. Nur gut, dass es weder beim TT noch beim Falcon eine besondere Obergrenze für die Kapazität der Platten gibt, die man anschließen kann. Gleiches gilt für den ST/STE mit ICD-kompatiblem Hostadapter wie LINK II oder LINK96/97. Auch bei IDE/EIDE-Platten hat man die freie Wahl, was die Kapazität angeht.
Immer häufiger finden sich bei Atari-Anwendern nicht nur Fest- und Wechselplatten, sondern auch Streamer, CD-ROM-Laufwerke oder Scanner auf SCSI-Basis. Diese Geräte werden auf niedrigster Ebene ähnlich angesteuert, wie es bei Festplatten der Fall ist. Dennoch sind die Unterschiede so groß, dass für jeden Gerätetyp individuelle Treiberroutinen erforderlich sind. Dies liegt nicht zuletzt daran, dass in diesem Zusammenhang auch die Art und Weise eine Rolle spielt, wie die Treiber in das Betriebssystem eingebunden werden müssen. Scheinen Festplatten und CD-ROM-Laufwerke auf dem ersten Blick viel gemeinsam zu haben, sind gerade hier die Unterschiede sehr deutlich. Das ist auch der Grund dafür, warum sich Fest- und Wechselplatten sowie CD-ROM-Laufwerke nicht mit einem einzigen Treiber bedienen lassen. Auf anderen Computerplattformen sieht es übrigens ähnlich aus. Auch hier werden die verschiedenen Gerätetypen durch eigene Treiber bedient. Der SCSI-2 Spezifikation ist zu entnehmen, dass es eine ganze Reihe vordefinierter SCSI-Gerätetypen gibt, als da wären:
Geräte vom Typ "Direct Access" und "Optical Memory" können in der Regel von Festplattentreibern angesprochen werden. Sie benutzen zwar andersartige Aufzeichnungsverfahren für die Datenspeicherung, sind aber ansonsten ähnlich zu behandeln. Bei einigen Geräten mit optischen Medien lässt sich der Gerätetyp durch einen Jumper zwischen "Direct Access" und "Optical Memory" umschalten. So lassen sich Festplattentreiber, sofern sie nicht schon von sich aus Geräte auf optischer Basis unterstützen, oft hinters Licht führen. Atarianer sind hiervon allerdings kaum betroffen, jedenfalls nicht bei der Verwendung eines aktuellen Treibers. Die Gerätetypen "CD-ROM" und "Sequential Access" sind vielen Anwendern bereits ein Begriff. Zum Gerätetyp "Processor" ist zu sagen, dass sich dahinter alles mögliche verbergen kann. Sogar Atari-Computer können, sofern als Festplattentreiber CBHD oder HDDRIVER zum Einsatz kommen, als Prozessor-Device fungieren und in einem gewissen Rahmen SCSI-Kommandos entgegennehmen. Einige Leser werden sicherlich demnächst ein Gerät dieses Typs an ihren Atari anschließen, ohne sich dessen bewußt zu sein: Die Ethernet- und ISDN-Adapter für den SCSI- bzw. ACSI-Bus, wie sie zur Zeit von WB Systemtechnik entwickelt werden, werden sich aller Voraussicht nach als SCSI-2 Prozessor-Devices melden. (Wir werden Sie in dieser Hinsicht natürlich auf dem laufenden halten.)
Es gibt also eine Vielzahl von SCSI-Geräten, mit zum Teil sehr speziellen Eigenschaften. Eines haben alle diese Geräte jedoch gemeinsam: Sie erfüllen den SCSI-2 Standard und können daher auf dieser Ebene durch einen einzigen Treiber, der ebenfalls diesem Standard genügt, angesteuert werden. Dies widerspricht nicht dem Anspruch des Betriebssystems, dass die Aufbereitung der übertragenen Daten je nach Gerätetyp unterschiedlich erfolgen muss. Das Betriebssystem schreibt lediglich in einem gewissen Rahmen vor, wie ein Treiber die Daten, die er von diesen Geräten erhält, abzuliefern hat. Wie der Treiber sich diese Daten jedoch besorgt, ist einzig und allein seine Sache. Es spricht deshalb nichts dagegen, dass sich Treiber für unterschiedliche SCSI-Peripheriegeräte eines weiteren zentralen Treibers bedienen, der für die gesamte Kommunikation über den SCSI-Bus verantwortlich ist. Ein solcher universeller Treiber, der nicht von vornherein auf bestimmte Geräte fixiert ist, wird oft auch als generischer Treiber bezeichnet. Bei vielen Betriebssystemen, für den Atari beispielsweise bei Linux, ist ein generischer Treiber ein wichtiger Grundbaustein.
Ein universeller SCSI-Treiber vereinfacht die Programmierung spezialisierter SCSI-Gerätetreiber erheblich. Da die eigentliche Kommunikation über den generischen Treiber abläuft, kann sich der Programmierer des Gerätetreibers ganz auf die wesentliche Aufgabe konzentrieren, also auf die speziellen Eigenschaften des SCSI-Gerätes, das angesteuert werden soll. Natürlich sind für die Treiberprogrammierung weiterhin Kenntnisse der SCSI-Spezifikation erforderlich, aber nicht bis ins kleinste Detail, wie es bei der kompletten Neuentwicklung eines Treibers der Fall wäre. Es reicht aus, die für das konkrete Gerät und die jeweilige Aufgabenstellung in Frage kommenden Kommandos zu kennen. Dabei handelt es sich größtenteils um Kommandos, wie sie in der SCSI-2 Spezifikation im einzelnen erläutert und standardisiert sind. Die Hersteller von SCSI-2 kompatiblen Geräten sind nämlich dazu angehalten, diese Spezifikation zu beachten, was durchaus Früchte getragen hat. Es werden nicht nur elektrische Eigenschaften festgelegt, sondern auch große Teile des Befehlssatzes von SCSI-Peripheriegeräten. Nicht umsonst lassen sich neue Festplatten in aller Regel ohne weiteres am Atari betreiben, und das häufig auch mit relativ alten Treibern. Nun soll es in dieser und der nächsten Ausgabe nicht darum gehen, von einem generischen SCSI-Treiber zu träumen und vielleicht umsonst darauf zu warten. Denn die gute Nachricht ist, dass es solche Treiber bereits gibt. Und das beste daran: Diese Treiber besitzen ein kompatibles Interface, da sie dieselbe Spezifikation erfüllen. Bei dieser Spezifikation handelt es sich um ein generisches SCSI-Interface mit dem Namen SCSIDRV, das von Steffen Engel ins Leben gerufen wurde. Unterstützt wird dieses Interface unter anderem von SCSIDRV.PRG, einem frei verfügbaren Programm für den AUTO- Ordner. Im wesentlichen mit SCSIDRV.PRG identisch ist SCSI.RAM, die Ausführung von SCSIDRV speziell für die Zusammenarbeit mit MagiC. Besonders komfortabel ist es, wenn das SCSIDRV-Interface bereits in einen Festplattentreiber integriert ist. Wer CBHD oder HDDRIVER 7 verwendet, bekommt so die SCSIDRV-Schnittstelle quasi gratis. Und das Schmankerl: SCSIDRV ist auch für MagiCMac und MagiCPC verfügbar. (Bei Redaktionsschluß lag die Version von MagiCP im Betastadium vor.) Dies heißt, dass alle Programme, die SCSI-Peripherie über dieses Interface ansteuern, ihre Funktion auch unter MagiCMac oder MagiCPC verrichten können.
Im folgenden soll die Rede davon sein, wie sich das SCSIDRV-Interface in der Praxis darstellt. Am Ende wird ein kleines Programm stehen, mit dem sich die Medien aller angeschlossenen SCSI-Geräte, sofern technisch möglich, auswerfen lassen. Es geht hier also nicht nur um die Medien von Wechselplatten, sondern auch um Streamer oder CD-ROM-Laufwerke. Zunächst sollte ich aber noch erwähnen, dass es bereits jetzt eine ganze Reihe von größeren Anwendungen für den Atari gibt, die das SCSIDRV- Interface nutzen. Bekannte Beispiele sind GEMAR (Backup-Software für Streamer), MUCKE (Player für Audio-CDs) oder SPIN! (Treiber für CD-ROM- Laufwerke). Und was natürlich besonders wichtig ist: Treiber mit Unterstützung für SCSIDRV sind im MausNet und Internet verfügbar [1], [2]. Die offizielle Dokumentation zum SCSIDRV-Interface liegt beiden Treibern bei.
Um möglichst flexibel zu sein, abstrahiert das SCSIDRV-Interface die SCSI-Schnittstelle, löst sich also von den auf den Atari fixierten Mechnismen und Begriffen und stellt den Zugriff auf die SCSI-Peripherie auf eine portable Basis. Einen wichtigen Stellenwert nimmt in diesem Zusammenhang der Bus ein. Dabei handelt es sich um eine Schnittstelle, an der SCSI-Geräte vorhanden sein können. Es kann mehrere solcher Schnittstellen geben, wie es in der Realität beim Atari TT auch tatsächlich der Fall ist. Im Gegensatz zur sonst üblichen hardwarenahen Programmierung auf dem Atari werden sämtliche Informationen über die vorhandenen Schnittstellen jedoch nicht anhand bestimmter Einträge im cookie jar gewonnen, sondern einzig und allein über Aufrufe der hierfür vorgesehenen Auskunftsfunktionen des SCSI-Interfaces. Lediglich die Verfügbarkeit des Interfaces sowie die Adressen der Routinen, die das Interface bereitstellt, werden durch den cookie SCSI signalisiert. Die wichtigsten Funkionen werde ich nun vorstellen, wobei zu beachten ist, dass es im Rahmen dieses Artikels nicht möglich ist, die Parameter aller Aufrufe im Detail zu beschreiben. Das gründliche Studium der Schnittstellen-Spezifikation ist daher unerläßlich. Anzahl und symbolische Namen der verfügbaren SCSI-kompatiblen Schnittstellen liefert InquireSCSI():
*LONG cdecl InquireSCSI(WORD what, tBusInfo Info);
Mit InquireSCSI() lassen sich grundlegende Informationen über alle vorhandenen SCSI-Schnittstellen abfragen. Dazu wird InquireSCSI() mehrfach aufgerufen. what besitzt beim ersten Aufruf den Wert cInqFirst, für alle weiteren Aufrufen cInqNext. Wer bereits Programmier-Erfahrung auf dem Atari oder auch auf PCs gesammelt hat, kennt diese Vorgehensweise bereits aus einem anderen Zusammenhang: Das Durchsuchen von Verzeichnissen nach Dateieinträgen geschieht mit derselben Methode. Man erhält solange neue Informationen geliefert, bis keine weiteren Daten mehr verfügbar sind. InquireSCSI() füllt die Struktur tBusInfo bei jedem Aufruf mit Daten über den nächsten verfügbaren SCSI-kompatiblen Bus. Bei diesen Daten handelt es sich insbesondere über einen symbolischen Namen (beispielsweise "ACSI", "SCSI" oder auch "ACSI (ICD)") und spezielle Eigenschaften dieses Busses. So ist Bus-Arbitrierung nur bei manchen Bussen möglich und auch der vollständige SCSI-Kommandosatz lässt sich nur auf bestimmten Bussen nutzen (insbesondere bei "SCSI" und "ACSI (ICD)").
Für jeden mit InquireSCSI() ermittelten Bus lassen sich mit InquireBus() die an diesem Bus vorhandenen Geräte ermitteln:
*LONG cdecl InquireBus(WORD what, WORD BusNo, tDevInfo dev);
BusNo ist dabei die Nummer eines Busses, wie sie von InquireSCSI() in der Struktur tBusInfo geliefert wird. Die Reihenfolge, in der InquireSCSI() diese Nummern liefert, ist willkürlich. Es ist lediglich definiert, dass der ACSI-Bus stets mit der Nummer 0 geführt wird, der SCSI-Bus der Ataris (egal ob TT oder Falcon) mit der Nummer 1. Weitere Annahmen über die Zuordnung dieser Nummern dürfen nicht gemacht werden. Überhaupt ist bei der Nutzung des SCSIDRV-Interfaces wichtig, dass jeder Aufruf einer Funktion dieses Interfaces nur mit Parametern erfolgen darf, die man im Vorfeld ebenfalls über das Interface erhalten hat. what besitzt bei InquireBus() eine ähnliche Bedeutung wie schon bei InquireSCSI(). Es werden der Reihe nach die IDs aller verfügbaren SCSI- Peripheriegeräte abgefragt. Um später auf eines dieser Geräte gezielt zugreifen zu können, liefert InquireBus() bei jedem Aufruf eine eindeutige ID zurück:
DLONG SCSIId;
Diese ID besteht aus zwei Langworten und hat nichts mit der tatsächlichen SCSI-ID des Gerätes zu tun. Die "wahre" SCSI-ID ist weder verfügbar, noch ist ihre Kenntnis erforderlich. Dieser Sachverhalt ist ungemein wichtig, da es nur so möglich ist, SCSI-Busse anzusprechen, bei denen es sich nicht um die allseits bekannten, bei den Ataris vorhandenen Busse handelt. Wie bereits erwähnt, ist SCSIDRV auch für MagiCMac und MagiCPC verfügbar, und auf Apple-Computern mag die SCSI-Hardare ganz anders aussehen als beim Atari. Die Verwendung einer "Pseudo-ID" wie beim SCSIDRV-Interface entkoppelt die Software von der Implementierung der SCSI-Schnittstelle auf Hardware-Ebene. So ist sichergestellt, dass SCSI- Software, die auf dem Atari unter Nutzung des hier vorgestellten Interfaces programmiert wurde, ohne Änderungen auch auf anderen Plattformen mit SCSIDRV-Unterstützung läuft.
Mit Hilfe der Information in SCSIId lässt sich nun ein beliebiges SCSI- Kommando an das Gerät schicken, das sich hinter dieser ID verbirgt. In der Regel wird man zunächst mit dem SCSI-Kommando INQUIRY in Erfahrung bringen, um welches Gerät es sich konkret handelt. Schließlich hat InquireBus() lediglich Angaben darüber geliefert, unter welchen IDs überhaupt Geräte vorhanden sind. Informationen über den Gerätetyp und den Namen besitzen wir bisher noch nicht. Das lässt sich aber leicht ändern. Hierzu öffnen wir mit Open() zunächst eine Verbindung zum Gerät mit einer der von InquireBus() erhaltenen SCSI-Ids:
**LONG cdecl Open(WORD BusNo, const DLONG SCSIId, ULONG MaxLen);
Die konkrete Auswahl eines bestimmten Gerätes erfolgt dabei ausschließlich über BusNo und SCSIId. Open() liefert ein Handle zurück, über das jeder weitere Zugriff auf dieses Gerät erfolgen wird. Der Handle-Mechanismus dürfte bereits von den Dateioperationen unter GEMDOS bekannt sein. Und wo es ein Open() gibt, existiert natürlich auch das Gegenstück Close():
LONG cdecl Close(tHandle handle);
Solange ein Handle für ein bestimmtes Gerät gültig ist, also noch kein Close() für dieses Handle aufgerufen wurde, lassen sich über das Handle mit den Operationen In() und Out() SCSI-Kommandos an das korrespondierende Gerät absetzen. Sollen im Rahmen einer solchen Operation Daten eingelesen werden, kommt In() zum Einsatz. Sollen Daten vom Computer zum Peripheriegerät übertragen werden, geschieht dies mit Out(). Findet keine Datenübertragung statt, beispielsweise bei TEST UNIT READY, lassen sich sowohl In() als auch Out() verwenden.
LONG cdecl In(tpSCSICmd Parms); LONG cdecl Out(tpSCSICmd Parms);
tpSCSICmd enthält alle Informationen, die für die erfolgreiche Ausführung des SCSI-Kommandos erforderlich sind. Dazu zählen insbesondere der SCSI- Kommandoblock sowie die Adresse eines Puffers, der bei Kommandos mit Datenübertragung von Bedeutung ist. Besonderheiten der Schnittstellen sind dabei für den Programmierer nicht von Belang. Man muss sich also insbesondere nicht darum kümmern, dass der ACSI-Bus beim TT keinen direkten Zugriff auf den gesamten Hauptspeicher erlaubt oder dass per ACSI eigentlich nur Vielfach von 16 Bytes übertragen werden können. Wer um die Besonderheiten des ACSI-Bus weiß, kann natürlich in Betracht ziehen, seinen Puffer von vornherein im ST-kompatiblen RAM anzulegen. Es besteht dann eine gewisse Wahrscheinlichkeit, dass der Overhead bei der Datenübertragung besonders gering ist. Meldet das SCSI-Gerät bei der Ausführung des Kommandos einen Fehler, fragen In() bzw. Out() optional mit REQUEST SENSE zusätzliche Informationen über diesen Fehler ab. Alles in allem ist es also ein leichtes, sich mit In() und dem SCSI-Kommando INQUIRY konkrete Angaben über das SCSI-Gerät zu besorgen, das sich hinter SCSIId verbirgt. Und genauso leicht lässt sich natürlich auch jedes andere SCSI-Kommando ausführen. Bei Kommandos höherer SCSI-Kommandoklassen ist allerdings darauf zu achten, ob diese vom vorliegenden Bus überhaupt unterstützt werden. Diese Information ist tBusInfo zu entnehmen. Beim ACSI-Bus ohne ICD-kompatiblen Hostadapter wird tBusInfo in der Regel signalisieren, dass das Senden beliebiger Kommandos nicht möglich ist. Nachdem die wichtigsten Aufrufe des SCSIDRV-Interface nun vorgestellt wurden, wird es Thema der nächsten Ausgabe sein, wie die Anwendung des Interfaces in der Praxis aussieht.
Literatur und Software:
[1] SCSIDRV.PRG/SCSI.RAM/CBHD:
CBHD502.TOS, Maus SZ (05341-852024) sowie andere Mailboxen im MausNet
http://members.aol.com/steffene
[2] HDDRIVER:
HDDRIV70.ZIP, Maus KA (0721-358887) sowie andere Mailboxen im MausNet
ftp: acp5.chemie.uni-kl.de/pub/atari/hddriver70_demo.zip
http://www.seimet.de/atari_german.html