Aufgepeppt: IDE-Platte nach Wahl

Die meisten Festplattentreiber für den ATARI sind recht wählerisch, wenn es um die Ansteuerung von IDE-Platten geht. So versteht sich insbesondere AHDI nur dann mit IDE-Geräten, wenn diese in der Lage sind, dem Treiber auf Anfrage ihre Geometrieparameter mitzuteilen. Dies ist aber bei einigen Modellen nicht der Fall.

Und es sind nicht nur Platten älteren Datums, die AHDI in Verlegenheit bringen. Auch einige aktuelle Typen von Western Digital und Conner machen Probleme. Wer noch nicht mit IDE-Platten am ATARI konfrontiert wurde und lediglich Erfahrungen mit SCSI-Platten gesammelt hat, wird sich wundern, daß es überhaupt Schwierigkeiten gibt. Schließlich lassen sich SCSI-Platten in der Regel ohne besondere Tricks an den ATARI anschließen, wobei ein ST natürlich mit einem SCSI-Host-Adapter ausgerüstet sein muß. Aber IDE ist halt nicht dasselbe wie SCSI, wie wir gleich sehen werden.

Gebremste Intelligenz

Genügt es bei SCSI-Platten, daß der Festplattentreiber zum Lesen und Schreiben von Sektoren lediglich Angaben über die gewünschte Sektornummer an die Platte schickt, erwartet eine IDE-Platte weitere Informationen. Übergeben werden muß die genaue Position des Sektors auf der Platte, also neben der Sektornummer auch die Nummer des Zylinders und des Kopfes, der für den gewünschten Sektor zuständig ist. Die intelligenteren SCSI-Platten hingegen berechnen sich diese Daten ohne die Hilfe des Festplattentreibers aus der Sektornummer.

Es mag nun der Eindruck aufkommen, daß die Ansteuerung von IDE-Platten umständlicher ist, als es bei SCSI-Platten der Fall ist. Schließlich muß der Treiber bei IDE-Geräten einige der Aufgaben übernehmen, die SCSI-Platten von sich aus erledigen können. In Wirklichkeit ist jedoch das Gegenteil der Fall. Das IDE-Interface ist nämlich recht simpel aufgebaut, sowohl was die Hardware als auch was die Ansteuerung per Software betrifft. Es genügt, in einige wenige Hardware-Register die gewünschten Daten zu schreiben, und die Übertragung beginnt. Dabei holt der Prozessor die Daten direkt vom Bus ab bzw. versorgt beim Schreibzugriff entsprechende Register der IDE-Hardware mit den benötigen Daten.

Der SCSI-Standard ist da deutlich anspruchsvoller und fordert, daß ein gewisses Busprotokoll eingehalten wird. Daher sind bei SCSI-Platten sehr viel mehr Aktionen notwendig, bevor man mit Daten versorgt wird. Dies kann dazu führen, daß die Übertragung kleiner Datenblöcke über den SCSI-Bus selbst bei einer schnellen Platte vergleichsweise langsam abläuft. Gerade bei kleinen Datenmengen nimmt das SCSI-Busprotokoll verhältnismäßig viel Zeit, verglichen mit der reinen Übertragungszeit, in Anspruch, was beim IDE-Bus nicht der Fall ist.

Moderne IDE-Platten im 3 1/2-Zoll-Format erlauben am Falcon übrigens überraschend hohe Übertragungsraten von bis zu 2.3 MByte/s und übertreffen damit sogar das Leistungsvermögen des SCSI-Busses von Falcon und TT.

Ausgetrickst

Zurück zur Schattenseite einiger Platten. Damit ein Treiber in der Lage ist, Sektornummern in die zugehörigen IDE-Geometriedaten umzurechnen, muß er die physikalischen Parameter der jeweiligen Platte kennen. Diese lassen sich über das IDE-Kommando IDENTIFY DRIVE ermitteln, das vom Treiber während des Boot-Vorgangs an die Platte abgeschickt wird. Als Antwort liefern die meisten IDE-Platten eine ganze Latte von plattenspezifischen Informationen, zu denen auch Angaben über die Zahl der Köpfe, Sektoren und Zylinder der Platte gehören. Manche Platten liefern bei IDENTIFY DRIVE jedoch keine oder falsche Geometrie werte mit dem Resultat, daß mit diesen Daten keine korrekte Umrechnung, also auch kein sinnvoller Plattenzugriff möglich ist.

Um AHDI trotz ungültiger Parameter verwenden zu können, ist es notwendig, daß die korrekten Parameter direkt in die Treiberdatei gepatcht werden. Auch die in HDX integrierten Treiberroutinen müssen diese Prozedur über sich ergehen lassen, damit die Platte überhaupt partitioniert werden kann. Um eine problematische IDE-Platte mit AHDI ohne Einschränkungen nutzen zu können, reicht es aber nicht aus, lediglich den eigentlichen Treiber zu patchen. Soll von dieser Platte gebootet werden, ist eine weitere Manipulation notwendig. Um den Treiber beim Boot-Vorgang überhaupt von der IDE-Platte laden zu können, müssen auch dem Ladeprogramm die Plattenparameter bekannt sein. Daher ist ein modifizierter Root-Sektor erforderlich, der wie schon AHDI bereits im Vorfeld mit den korrekten Geometrieparametern versehen werden muß.

Wir schreiten zur Tat

Das Programm AHDI2IDE bringt AHDI und den Root-Sektor einer IDE-Platte auf Vordermann. Die Anwendung läuft in mehreren Schritten ab, die einer modifizierten Partitionierung und Treiberinstallation mit HDX und HINSTALL entsprechen. Legen Sie zunächst eine Kopie der Originaldiskette mit der ATARI-Treiber-Software in Floppy A und starten sie das Patch-Programm. AHDI2IDE geht davon aus, daß die Treiberdiskette mindestens die folgenden Programme enthält:

    A:\AUTO\AHDI.PRG
    A:\HDX\HDX.PRG
    A:\HINSTALL\SHDRIVER.RAW

Beim Start prüft AHDI2IDE zunächst, ob sich die IDE-Einheit 0 bereits ansprechen läßt, ob also schon ein Festplattentreiber für den IDE-Bus installiert ist. Falls nicht, gibt das Programm die Plattenparameter so auf dem Bildschirm aus, wie sie von der Festplatte per IDENTIFY DRIVE geliefert wurden. Sie haben nun die Möglichkeit, für die Zahl der Zylinder, Köpfe und der Sektoren pro Spur neue Werte vorzugeben. Um welche Daten es sich handeln muß, ist dem Datenblatt der jeweiligen Platte zu entnehmen. Nach der Eingabe der Daten und einer Sicherheitsabfrage werden die AHDI- und HDX-Programmdateien gepatcht, und AHDI2IDE beendet sich.

Nun ist es Ihre Aufgabe, die IDE-Platte mit dem modifizierten HDX auf der Treiberdiskette zu partitionieren. Dieser Schritt wäre mit dem unveränderten HDX schon gar nicht mehr möglich gewesen, da HDX genau wie AHDI nur dann auf eine IDE-Platte zugreifen kann, wenn diese brauchbare Geometrieparameter liefert. Unter der Voraussetzung, daß die Plattenparameter innerhalb von AHDI2IDE korrekt eingegeben wurden, läßt sich die IDE-Platte dagegen fehlerfrei ansprechen und kann partitioniert werden. Nach dem Partitionieren starten Sie AHDI von Diskette und installieren anschließend mit HINSTALL den gepatchten Festplattentreiber auf Ihrer Boot-Partition. Soll nicht von der IDE-Platte gebootet werden, ist die Sache damit bereits erledigt. Sie sind nun im Besitz einer AHDI-Version, die speziell für Ihre IDE-Platte gepatcht wurde. Aber Vorsicht: Dieser AHDI kann nicht mit IDE-Platten betrieben werden, die eine abweichende Geometrie aufweisen, denn schließlich sind im Treiber die Parameter einer ganz bestimmten Platte fest vermerkt.

Booten gefällig?

Um von der partitionierten Platte booten zu können, ist ein zusätzlicher Schritt erforderlich. Beim Booten wird durch Programme auf dem ausführbaren Root- und Boot-Sektor der Festplatte die Treiberdatei SHDRIVER.SYS nachgeladen, die von HINSTALL auf der Platte installiert wird. Die Treiberdatei läßt sich aber nur dann laden, wenn bereits beim Booten, also noch vor dem Laden der Datei, die Parameter der Platte vom Betriebssystem ermittelt werden konnten. Ist dies nicht der Fall, muß der Root-Sektor der Platte derart modifiziert werden, daß die Plattenparameter dort fest eingetragen werden. Diese Aufgabe erledigt AHDI2IDE dann, wenn das Programm nach dem Start feststellt, daß bereits ein Zugriff auf die IDE-Einheit 0 möglich ist. In diesem Fall wird nach der Abfrage der Plattenparameter nicht, wie oben erläutert, die Treiber-Software gepatcht, sondern es wird nach einer Sicherheitsabfrage ein neuer Root-Sektor auf die IDE Einheit 0 geschrieben, der die korrekten Plattenparameter enthält und dadurch ein Booten von der IDE-Platte erlaubt. Unabhängig vom Root-Sektor ist ein Booten vom IDE-Bus normalerweise nur dann möglich, wenn Ihr ATARI mit TOS 2.06 oder neueren Versionen ausgestattet ist. Ältere TOS-Varianten können den IDE-Bus nicht ansprechen, sind also nicht in der Lage, den Root-Sektor der Platte zu laden. Ähnlich sieht es bei MagiX! 2.0 aus. Auch hier kann nicht vom IDE-Bus gebootet werden. Spätestens mit dem Erscheinen von MagiX! für den Falcon030 wird sich dies natürlich ändern.

Ein positiver Nebeneffekt des von AHDI2IDE erzeugten Root-Sektors ist, daß sich mit ihm unabhängig von der verwendeten IDE-Platte schneller vom IDE-Bus booten läßt, als es mit dem Standard-Root-Sektor möglich wäre. Dies liegt daran, daß der Plattentreiber von TOS über den XBIOS-Aufruf DMAread geladen wird. DMAread ist beim IDE-Bus jedoch langsamer als die neue Laderoutine im von AHDI2IDE erzeugten Root-Sektor. Daß auch bei ungültigen Plattenparametern ein Zugriff zumindest auf den Rootsektor jeder IDE-Platte möglich ist, liegt übrigens daran, daß dieser Sektor unabhängig von der Plattengeometrie stets auf Zylinder 0, Sektor 0, Kopf 0 zu finden ist. Das Laden des Root-Sektors gelingt daher stets unabhängig von den Geometriedaten einer Platte.

Randbemerkungen

Programme, die wie AHDI2IDE einen Patch durchführen, sind prinzipbedingt in einem gewissen Maße unsauber. So ist die einwandfreie Funktion von AHDI2IDE nur dann gewährleistet, wenn sich der Code von AHDI und HDX an der Stelle, die von AHDI2IDE gepatcht wird, nicht ändert. Zur Zeit versteht sich AHDI2IDE mit allen AHDI-Versionen ab AHDI 5.00, einschließlich der aktuellen Version AHDI 6.061.

Ein neuer Root-Sektor darf von AHDI2IDE nur auf Platten geschrieben werden, die vorher voll ATARI-kompatibel partitioniert wurden. Dies trifft in der Regel nicht auf Platten zu, die mit der Festplatten-Software von ICD eingerichtet wurden. Erst neuere Versionen dieser Software erlauben ein ATARI-konformes Format.

Was die Übersetzung der C- und Assembler-Quelltexte zu AHDI2IDE angeht, kann diese ohne Änderung mit dem Pure-C-Compiler und -Assembler erfolgen. Andere C-Compiler sollten aber ebenfalls mit den Quellen klarkommen.

Aller guten Dinge sind zwei

Nachdem nun die Verwendung beliebiger IDE-Platten am Falcon030 und mit entsprechenden IDE-Host-Adaptern auch am ST/ STE recht problemlos möglich ist, mag man mit dem Gedanken spielen, gleich zwei solcher Platten am ATARI betreiben zu wollen. (Mehr als zwei Platten läßt der IDE-Bus übrigens nicht zu.) Wer dies vorhat, sollte jedoch wissen, daß AHDI nur die IDE-Einheit 0 unterstützt. Zwei IDE-Platten (Master und Slave) lassen sich dagegen mit Festplattentreibern von Fremdanbietern ansprechen, speziell mit HuSHI und HDDRIVER. Diese Treiber unterstützen darüber hinaus das XHDI-Protokoll [1], da’s u.a. komfortable Möglichkeiten zur Kommunikation mit Festplatten bietet.

US (mit Hilfe von Informationen von Jens Fellmuth)

Literatur:

[1] Julian F. Reschke, „Die XHDI-Spezifikation“, ST-Magazin 6/92

/* Listing 1; AHDI2IDE.C 
    (c)1994 by MAXON-Computer
    **Autor:** Uwe Seimet
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tos.h>

#define FALSE 0
#define TRUE 1

typedef int boolean;

/* IDE-Parameter, wie sie von IDENTIFY DRIVE geliefert werden */

typedef struct {
    int flags;
    int cyls;
    int reserved1;
    int heads;
    int bpt;
    int bps;
    int spt;
    int reserved2[3]; 
    char serial[20];
    int type;
    int size;
    int ecc;
    char firmware[8];
    char model[40];
    int reserved3[82];
    char reserved4[256];
} IDEPARS;

IDEPARS buffer;

int heads, spt, cyls;

char driver[1000001];

int root[512];

/* Funktions-Prototypen */

boolean get_idepars(void); 
boolean patch(char *filename); 
boolean install_root(void);

extern int testide(void);
extern int identify(IDEPARS *buffer);
extern int Start[], end[];
extern char idepars[2];

int main()
{
    char input; 
    long oldstack = 0; 
    int Status;

/* Auf IDE-Hardware prüfen */

    if (!Super ((void *)1L)) oldstack = Super (0L); 
    status = testide();
    if (oldstack) Super ((void *)oldstack);

    if (!Status) {
        printf("Keine IDE-Hardware vorhanden!\n"); 
        return(0);
    }

    if (!get_idepars()) {
        printf("Fehler beim Holen der Plattenparameter!\n"); 
        return(0);
    }

/* IDE-Treiber bereits installiert? */

    if (!Rwabs(8, root, 1, 0, 18)) { 
        install_root(); 
        return(0);
    }

    printf("AHDI mit diesen Parametern patchen? (j/ n) ") ;

    do
        input = getchar(); 
    while ((input != 'j') && (input != 'n'));

    if (input != 'j') return(0);

    printf("\n\n");

    status = patch("a:\\auto\\ahdi.prg"); 
    if (!status) {
        printf("Fehler beim Patchen vom AHDI.PRG!\n"); 
        return(0);
    }

    status = patch( "a:\\hinstall\\shdriver.raw"); 
    if (!status) {
        printf("Fehler beim Patchen vom SHDRIVER.RAW!\n"); 
        return(0);
    }

    status = patch("a:\\hdx\\hdx.prg"); 
    if (!status) {
        printf("Fehler beim Patchen vom HDX.PRG!\n");
        return(0);
    }

    return(0);
} /* main */

boolean get_idepars()
{
    long oldstack = 0;
    int Status;
    char dummy[40];

/* Plattenparameter holen */

    if (!Super ((void *)1L)) oldstack = Super (0L);
    status = identify(&buffer);
    if (oldstack) Super ((void *)oldstack);
    if (Status) return(FALSE);

    buffer.reserved3[0] = 0;
    printf("Aktuelle Parameter von IDE-Einheit 0:\n\n");
    printf("Platte: %s\n", buffer.model);
    sprintf(dummy, "%d", buffer.heads);
    printf("Köpfe: %s\n", dummy);
    sprintf(dummy, "%d", buffer.spt);
    printf("Sektoren pro Spur: %s\n", dummy);
    sprintf(dummy, "%d", buffer.cyls);
    printf("Zylinder: %s\n\n\n", dummy);

    printf("Neue Parameter:\n\n");
    printf("Köpfe: ");
    scanf("%d", fcheads);
    printf("Sektoren pro Spur: ");
    scanf("%d", &spt);
    printf("Zylinder: ");
    scanf("%d", &cyls);

    return(TRUE);
} /* get_idepars */

/* Treiberdatei patchen */

boolean patch(filename)
char *filename;
{
    long len;
    int handle;
    char *ident;
    int *dummy;

    printf("Patche %s\n", filename);

    handle = open(filename, 0_RD0NLY);
    if (handle < 0) return(FALSE);
    len = read(handle, driver, 1000001);
    close (handle);
    if (len < 0) return(FALSE);

    /* "CP2024"-Kennung dient als Anhaltspunkt
    für das Auffinden der zu patchenden Sequenz */

    ident = driver;
    while (TRUE) {
        ident = memchr(ident, 'C', len-(ident-driver));
        if (ident == NULL) return(FALSE);
        if (!strncmp(ident, "CP2024", 6)) break;
        else ident++;
    }

/* Neue Parameter in Treiber eintragen */

    dummy = (int *)(ident-74);
    dummy[0] = 0x303c; /* MOVE #,D0 */
    dummy[1] = cy1s;
    dummy[2] = 0x323c; /* MOVE #,D1 */
    dummy[3] = heads;
    dummy[4] = 0x343c; /* MOVE #,D2 */
    dummy[5] = spt;
    dummy[6] = 0x4e75; /* RTS */

    handle = open(filename, O_WRONLY);
    if (handle < 0) return(-1);
    if (write(handle, driver, len) != len) {
        close(handle);
        return(FALSE);
    }
    close (handle);

    return(TRUE);
} /* patch */

/* Neues Rootprogramm installieren */

boolean install_root()
{
    char input;
    int len, checksum = 0;
    register int i;

    printf("\n\nSoll ein neuer Rootsektor installiert werden? (j/n)");

    do
        input = getchar();
    while ((input != 'j’) && (input != 'n'));

    if (input != 1 j ' ) return(TRUE);

/* Parameter für IDE-Einheit 0 eintragen */

    idepars[0] = heads;
    idepars[1] = spt;

/* Rootprogramm kopieren */

    len = (int)(end-start);
    for (i=0; i<len; i++) root[i] = start[i];

/* Rootsektor ausführbar machen */

    for (i=0; i<255; checksum += root[i++]);
    root[i] = 0x1234-checksum;

/* Neuen Rootsektor zurückschreiben */

    if (Rwabs(9, root, 1, 0, 18)) return(FALSE);

    return(TRUE);
} /* install_root */

Listing 1: Der C-Quelltext zu AHDI2IDE

* Listing 2; AHDIBOOT.S 
* (c)1994 by MAXON-Computer 
* **Autor:** Uwe Seimet 

BIOS = 13 
KBSHIFT = 11 

XBIOS = 14 
DMAREAD = 42 

*Einige Systemvariablen

_bootdev = $446 
_hz_200 = $4ba 
_drvbits = $4c2 
_sysbase = $4f2 
pun_ptr = $516 
_p_cookies = $5a0 

*Hardware-Register, von Atari
*nicht dokumentierte IDE-Register :-)

gpip = $fffffa01 

idedr = $fff00000 ;Data Register (R/W)
idesc = $fff00009 ;Sector Count (R/W)
idesn = $fff0000d ;Sector Number (R/W)
idecl = $fff00011 ;Cylinder Low (R/W)
idech = $fff00015 ;Cylinder High (R/W)
idesdh = $fff00019  ;Drive/Head (R/W)
idecr = $fff0001d ;Command Register (W)
idesr = $fff0001d ;Status Register (R)
idedor = $fff00039  ;Device Control (W)
ideasr = $fff00039  ;Alternate Status (R)

*Rootprogramm für Booten von IDE-Bus

    globl Start,end,idepars

start:
    bra.s .srstart
    bra .srread

.srstart:clr.1 pun_ptr
    bclr #2,_drvbits+3
    movem.l d3/d5,-(sp)
    move #-1,-(sp)
    move #KBSHIFT,-(sp)
    trap #BIOS
    addq.l #4,sp
    btst #3,d0
    bne.s .srexit
    btst #0,d0 ;Shift rechts?
    beq.s .noshift ;nein-
    tst.b d5
    beq.B .noshift ;keine Präferenz
    eor.b #$c0,d5 ;Maske wechseln
.noshift:moveq #3,d0
    moveq #-$08,d1
    lea start+$1c6(pc),a0
    cmp.l #"DMAr",d3 ;Booten von SCSI/IDE-Bus?
    beq.s .dma /ja-
    moveq #-$80,d2 ;Präferenz TOS
    bra.s .test1
.dma: move.b d5,d2
    beq.s .test2
.test1: btst #0,(a0) ;Booten mit Präferenz
    beq.s .noval1
    and.b d1,(a0)
    cmp.b (a0),d2
    beq.s .srtos
.noval1:lea 12(a0),a0
    dbra d0,.test1
    bra.s .srexit
.test2: btst #0,(a0) /Booten ohne Präferenz
    beq.s .noval2
    and.b d1,(a0)
    bne.s .srtos
.noval2:lea 12(a0),a0
    dbra d0,.test2
.srexit:movem.1 (sp)+,d3/d5
.tostest:clr _bootdev
    move.1 _sysbase,a0
    move.l $18(a0),d0
    swap d0
    cmp.l #$19870422,d0 ;altes TOS?
    bcc.s .srret ;nein-
    move #$e0,d7
.srret: rts
.srtos: move.l 4(a0),d6
    moveq #1,d5
    lea start+512(pc),a4
    bsr.s .srread
    tst d0
    bne .srexit
    move.l a4,a0
    move.w #$ff,d1
    moveq #0,d0
.srchk: add (a0)+,d0
    dbra d1,.srchk
    cmp #$1234,d0
    bne .srexit ;nicht ausführbar-
    lea .srread(pc),a3
    lea .tostest(pc),a5
    movem.l (sp)+,d3/d5
    jmp (a4) ;Bootprogramm ausführen
.srread:btst #4,d4
    bne.s .sride ;Booten von IDE-Bus-
    move d4,-(sp)
    pea (a4)
    move d5,-(sp)
    move.1 d6,-(sp)
    move #DMAREAD,-(sp)
    trap #XBIOS
    lea 14(sp),sp
    rts

*Die folgenden Routinen entstanden in
*Anlehnung an Ideen von Jens Fellmuth

.sride: lea idepars(pc),a6
    tst.b (a6)
    bne.s .pars ;IDE-Parameter sind vorhanden-
    move.b d4,d0
    and.b #1,d0
    asl.b #4,d0
    or.b #$a0,d0
    move.b d0,idesdh
    move.1 a4,a0
    moveq #0,d1*
    move.b # 0,idedor
    move.b #$ec,idecr ;IDENTIFY DRIVE
    bsr.s .w4int
    bne.s .err
    move.b 7(a4),(a6) ;Köpfe
    move.b 13(a4),1(a6) ;Sektoren pro Spur
.pars: move.l d6,d1
    moveq #0,d0
    move.b 1(a6),d0
    moveq #0,d2
    move.b (a6),d2
    mulu d0,d2
    divu d2,d1
    move.b d1,idecl ;Cylinder low
    lsr.l #8,d1
    move.b d1,idech ;Cylinder high
    lsr.l #8,d1
    divu d0,d1 ;Head
    move.b d4,d0
    and.b #1,d0
    asl.b #4,d0
    or.b d0,d1
    or.b #$a0,d1 ;Drive 0 (Master)
    move.b d1,idesdh
    swap d1
    addq #1,d1
    move.b d1,idesn ;Sector number
    move.l a4,a0
    move.b d5,idesc ;Sector count
    move d5,d1
    subq #1,d1
    move.b #0,idedor
    move.b #$20,idecr ;READ SECTOR
.w4int: move.l #$7d0,d0
    add.l _hz_200,d0
.wait: btst #5,gpip
    beq.s .cont
    cmp.l _hz_200,d0
    bhi.s .wait
.err: moveq #-1,d0
    rts
.cont: move.b idesr,d0
    btst #0,d0
    bne.s .err
    btst #3,d0
    beq.s .err
    moveq #63,d0
    lea idedr,a1
.loop: move.l (a1),(a0)+
    move.1 (a1),(a0)+
    dbra d0,.loop
    dbra d1,.w4int
    moveq #0,d0
    rts
idepars:dcb.b 2,0
end: dc.b 0

    even

    globl testide,identify

*Auf IDE-Hardware testen

testide:
    pea (a2)
    sub.1 a2,a2
    move.1 _p_cookies,d0
    beq.s nocook

    move.l d0,a0
cook: movem.l (a0)+,d0-d1
    tst.l d0
    beq.s nocook
    cmp .1 #" _CPU",d0
    bne.s cook
    cmp #10,d1
    bcs.s nocook
    movec vbr,a2

nocook:
    moveq #0,d0
    move sr,-(sp)
    ori #$0700,sr
    move.l sp,a1
    move.l $08(a2),a0
    move.l #nide,$08(a2)
    tst.b idecl
    moveq #-1,d0
nide: move.l a0,$08(a2)
    move.l a1,sp
    move (sp)+,sr

    move.1 (sp)+,a2
    rts

identify:
    pea (a2)
    move.l a0,a1
    move.b #$a0,idesdh
    moveq #-1,d0
    tst.b idedor
    ble.s idret
    move.b #0,idedor
    move.b #$ec,idecr ;IDENTIFY DRIVE
    move.l #500,d0
    bsr wait2
    bmi.s idret
    btst #3,d0
    beq.s idret
    bsr.s readbuf
    moveq #0,d0
idret: move.l (sp)+,a2
    rts

*Daten von IDE-Bus abholen

readbuf:
    move.l a1,a0
    move #255,d0
    lea idedr,a2
rloop: move (a2),(a1)+
    dbra d0,rloop
    move.l a0,a1
    rts

*IDE-Interrupt abwarten

w4int:
    move.l #$7d0,d0
wait2: add.l _hz_200,d0
wide: btst #5,gpip
    beq.s wcont
    cmp.l _hz_200,d0
    bhi.s wide
    moveq #-1,d0
    rts
wcont: moveq #0,d0
    move.b idesr,d0
wret: rts

Listing 2: Der Assembler-Quelltext zu AHDI2IDE
Uwe Seimet


Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]