Autor Thema: lesen von diskette mit fdc und dma. finde den fehler nicht  (Gelesen 3524 mal)

nore

  • Beiträge: 76
    • Profil anzeigen
Gespeichert
hi, ich hab zum lesen eines tracks von diskette einen kleinen sofware-interrupt geschrieben, den ich dann mit einer funktion aufrufe. der hat anfangs sowohl unter bochs als auch an diversen richtigen PCs funktioniert. seit ungefähr einer woche tut er dies allerdings nicht mehr. unter bochs funktioniert es noch, aber am richtigen PC nicht mehr.
das interessante daran ist: ich habe unmittelbar davor an der ISR dieses interrupts nichts geändert. ich habe jetzt schon einige stunden mit fehlersuchen verbracht und bin mittlerweile echt am verzweifeln.

anbei poste ich den code der ISR und hoffe, ihr könnt mir helfen.

kurze bemerkungen: in eax steht beim aufruf die adresse, an die der track geladen werden soll, in ch steht der kopf und in cl der zylinder.
die funktion delay funktioniert (unabhängig von diesem interrupt getestet) und erwartet millisekunden in einem unsigned long.
ob der track in den arbeitsspeicher geladen wurde teste ich mit einer funktion, die mit sehr großer wahrscheinlichkeit fehlerfrei läuft (andere speicherstellen werden richtig angezeigt).

hier also der code der ISR:

  _int_0x30:
  push edx
  push eax
    mov al, 0x14
    out 0x08, al               ; dma deaktivieren
    mov al, 0x56
    out 0x0b, al               ; einzel, adressinc, kein autoinit, schreiben, kanal2
  pop eax
    out 0x0c, al               ; flip-flop leeren
    out 0x04, al               ; niederwertiges adressbyte schicken
    shr eax, 8
    out 0x04, al               ; höherwertiges adressbyte schicken
    shr eax, 8
    out 0x81, al               ; page-byte senden
    out 0x0c, al               ; flip-flop leeren
    mov al, 0xFF
    out 0x05, al               ; wie viele zugriffe (bytes)(niederwertiges byte)  (gesamtzugriffe-1=angegebene zahl)
    mov al, 0x23
    out 0x05, al               ; wie viele zugriffe (bytes)(höherwertiges byte)
    mov al, 0x02
    out 0x0A, al               ; mögliche maskierung aufheben
    mov al, 0x10
    out 0x08, al               ; dma wieder aktivieren

    mov     al, 0x1c
    mov     dx, 0x03f2
    out     dx ,al           ; diskettenlaufwerks-motor einschalten (laufwerk A, über dma, ...)

    mov al,7
    call writediskdata
    mov al,0
    call writediskdata       ; neu kalibrieren

    mov al,3
    call writediskdata
    mov al,0x0F
    call writediskdata
    mov al,2
    call writediskdata       ; laufwerkdaten festlegen

    mov al, 0x46             ; erstes byte des read-befehls
    call writediskdata
    mov al, ch
    shl al, 2                ; head
    call writediskdata
    mov al, cl               ; cylinder
    call writediskdata
    mov al, ch               ; head
    call writediskdata
    mov al, 1                ; sector
    call writediskdata
    mov al, 2                ; sectorsize (128*2^2)
    call writediskdata
    mov al, 18               ; secpertrack
    call writediskdata
    mov al, 27               ; länge von GAP3 (??)
    call writediskdata
    mov al, 0xFF             ; bytes to read (standaradwert, da sectorsize!=0) (??)
    call writediskdata

    push dword 0x400   ;1024
    call _delay
    pop eax

    mov     al, 00h
    mov     dx, 0x03f2
    out     dx,al           ; motor wieder aus
  pop edx
  iret

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #1 am: 03. April 2006, 23:07 »
Hmm... also wo positioniert du denn den Kopf? Das war nämlich früher auch mein Fehler, als es nur unter den Emulatoren funktionierte, aber nicht auf echten PCs. Dann habe ich den Kopf positioniert und es funktionierte. Hier wie man das macht:

mov bl,0Fh ;Seek (positionier) Kommando
call fdc_sendbyte
mov bl,Drive ;Laufwerk
call fdc_sendbyte
mov bx,di ;Spur
call fdc_sendbyte


bitmaster

PS: Dann hätte ich noch eine Bitte. Wie sieht der Code deiner delay-Funktion aus? Ich versuche nämlich so eine Funktion in den PM zum laufen zu bekommen. Bis jetzt vergeblich.

Danke!!!
In the Future everyone will need OS-64!!!

nore

  • Beiträge: 76
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 04. April 2006, 14:27 »
zunächst mal danke für den tipp.

für mein delay brauch ich einmal irq0:

  _int_irq_0:
    cli
    push eax
    mov eax, [_timer]
    inc eax
    mov [_timer], eax
    mov al, 0x20
    out 0x20, al
    pop eax
    sti
  iret
  _timer dd 0

und dann noch die funktion an sich (in c):

void delay(unsigned long ms)
{
  unsigned long startz;
  ms*=182;
  ms/=10000;
  if (ms>(0x0-timer)) timer=0;
  startz=timer;
  while (startz+ms>timer){;};
}


ich konnte deinen tipp mit dem seek gar nicht testen, weil jetzt auf einmal (war vorher wirklich noch nicht und besteht auch, wenn ich den seek-teil wieder rausnehme) an der stelle, an der ich die delay-funktion aufrufe eine endlosschleife entsteht.  ich hab sogar nochmal geguckt, wie c die funktion aufruft und das ganze dann auch so gemacht. ich bin bald echt am verzweifeln.

ich poste jetzt nochmal den code meiner momentanen isr, die einen track von diskette head ch, cylinder cl an [eax] laden soll. ich bin mir ziemlich sicher, dass die endlosschleife bei "call _delay" entsteht. wenn ich das wegmache, entsteht keine. außerdem bleibt der diskettenlaufwerksmotor an.


  _int_0x30:
  push edx
  push eax
    mov al, 0x14
    out 0x08, al               ; dma deaktivieren
    mov al, 0x56
    out 0x0b, al               ; einzel, adressinc, kein autoinit, schreiben, kanal2
  pop eax
    out 0x0c, al               ; flip-flop leeren
    out 0x04, al               ; niederwertiges adressbyte schicken
    shr eax, 8
    out 0x04, al               ; höherwertiges adressbyte schicken
    shr eax, 8
    out 0x81, al               ; page-byte senden
    out 0x0c, al               ; flip-flop leeren
    mov al, 0xFF
    out 0x05, al               ; wie viele zugriffe (bytes)(niederwertiges byte)  (gesamtzugriffe-1=angegebene zahl)
    mov al, 0x23
    out 0x05, al               ; wie viele zugriffe (bytes)(höherwertiges byte)
    mov al, 0x02
    out 0x0A, al               ; mögliche maskierung aufheben
    mov al, 0x10
    out 0x08, al               ; dma wieder aktivieren

    mov     al, 0x1c
    mov     dx, 0x03f2
    out     dx ,al           ; diskettenlaufwerks-motor einschalten (laufwerk A, über dma, ...)

    mov al,7
    call writediskdata
    mov al,0
    call writediskdata       ; neu kalibrieren
   
    mov al,3
    call writediskdata
    mov al,0x0F
    call writediskdata
    mov al,2
    call writediskdata       ; laufwerkdaten festlegen    
   
    mov al,0Fh               ;Seek (positionier) Kommando
    call writediskdata
    mov al, ch
    shl al, 2                ; head
    call writediskdata
    mov al,cl                ;Spur
    call writediskdata
   
    mov al, 0x46             ; erstes byte des read-befehls
    call writediskdata
    mov al, ch
    shl al, 2                ; head
    call writediskdata
    mov al, cl               ; cylinder
    call writediskdata
    mov al, ch               ; head
    call writediskdata
    mov al, 1                ; sector
    call writediskdata
    mov al, 2                ; sectorsize (128*2^2)
    call writediskdata
    mov al, 18               ; secpertrack
    call writediskdata
    mov al, 27               ; länge von GAP3 (??)
    call writediskdata
    mov al, 0x00             ; bytes to read (standardwert, da sectorsize!=0) (??)
    call writediskdata
 
      push dword 0x7d0         ; 2000
      call _delay
      add esp, 0x4
     
      mov     al, 00h
      mov     dx, 0x03f2
      out     dx,al           ; motor wieder aus
  pop edx
  iret

nore

  • Beiträge: 76
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 05. April 2006, 16:41 »
ok, mein letztes problem hebt sich auf, wenn ich den delay-aufruf und das ausschalten des motors aus der isr rausnehme. werden, wenn ein software-interrupt noch nicht fertig abgearbeitet ist, keiner hardwareinterrupts zugelassen?
 
aber trotz seek-kommando stehen an der stelle im arbeitsspeicher, an die ich den track lesen will immer nur nullen. muss ich da vllt auch noch delays einfügen oder sonst irgendwie abfragen, ob das seek-kommando beendet ist? ich werd mal gucken, ob ich das hinbekomme, ich editier dann später noch was rein.

EDIT1: anscheinend braucht das seek-kommando wirklich zeit.
EDIT2: da anscheinend weder ein hardwareinterrupt aufgerufen wird, noch sonst etwas funtkioniert, um rauszufinden, ob der vefehl fertig ist, muss ich wohl oder über nach dem calibrate und nach dem seek je ein selay einfügen.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #4 am: 05. April 2006, 19:18 »
Zitat von: nore
ok, mein letztes problem hebt sich auf, wenn ich den delay-aufruf und das ausschalten des motors aus der isr rausnehme. werden, wenn ein software-interrupt noch nicht fertig abgearbeitet ist, keiner hardwareinterrupts zugelassen?
 
aber trotz seek-kommando stehen an der stelle im arbeitsspeicher, an die ich den track lesen will immer nur nullen. muss ich da vllt auch noch delays einfügen oder sonst irgendwie abfragen, ob das seek-kommando beendet ist? ich werd mal gucken, ob ich das hinbekomme, ich editier dann später noch was rein.

EDIT1: anscheinend braucht das seek-kommando wirklich zeit.
EDIT2: da anscheinend weder ein hardwareinterrupt aufgerufen wird, noch sonst etwas funtkioniert, um rauszufinden, ob der vefehl fertig ist, muss ich wohl oder über nach dem calibrate und nach dem seek je ein selay einfügen.
Ich habe zwar gehört das nach dem positionieren des Kopfes eine delay-Funktion eingebaut werden muss. Aber ich habe bei mir keine delay-Funktionen und es funktioniert auf allen PCs die ich besitze und auf allen Emulatoren die ich kenne. Nur ist das bei mir alles ziemlich langsam. Ich werde es später mal mit einer delay-Funktion bei mir ausprobieren. Intel spricht glaube ich von 500 Millisekunden. Der IRQ6 wird nur nach einem Schreib-/Lesebefehl ausgeführt und wenn der Kopf positioniert wird. Mein Code des IRQ6 setzt lediglich eine Variable auf 1. Und nach dem Schreib-/Lesebefehl und Positionieren des Kopfes prüfe ich einfach ob die Variable den Wert eins hat. Wenn nicht dann wird weiter geprüft, solange halt bis die Variable den Wert eins hat. Dann wenn sie den Wert eins hat, kann vortgefahren werden (aber dann auch die Variable wieder auf Null setzten bzw <> 1). Das heißt, dass erst weiter gemacht wird, wenn der IRQ6 ausgeführt wurde. Deswegen finde ich es auch blöd das man zusetzlich noch eine delay-Funktion einbauen sollte. Aber der fdc ist meiner Meinung nach sowieso schlecht durchdacht.

bitmaster
In the Future everyone will need OS-64!!!

nore

  • Beiträge: 76
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 10. April 2006, 16:34 »
ok, danke. aber ich löse das trotzdem jetzt mit delay, weil ichs anders nicht hinbekomme.

EDIT: ich mach mal nen neuen thread für die neue frage auf, ist ja nicht mehr das gleiche.

 

Einloggen