Autor Thema: Diskettencontroller  (Gelesen 3292 mal)

MeisterProppa

  • Beiträge: 11
    • Profil anzeigen
    • http://www.alles-flaschen.de
Gespeichert
« am: 23. June 2004, 23:38 »
Hallo, ich bins wieder...
Von dem Anfangsstadium bei meiner ersten Frage habe ich mich schon etwas entfernt. Ich habe inzwischen einen keyboard-Treiber mitsamt scan-Funktion für den Input, dann habe ich ein einfaches Paging-System eingebaut und versuche mich mal darin den Floppycontroller anzusprechen.
Ich starte also den Motor und schicke ein ReadSector Command ab. Das Laufwerk reagiert und sendet einen Interrupt #6 zurück...
Und hier setzt mein Problem an: Trotz Googlen habe ich keine Ahnung, in welchen Ports jetzt welche Daten stehen, die mein ReadSector zurückgegeben hat.
Kennt jemand da eine gute Übersicht oder ein Tutorial, in dem das beschrieben ist?

GhostCoder

  • Beiträge: 187
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 24. June 2004, 10:14 »
Hiho,

ReadSector nutzt dma. Man kann das zwar ausstellen, aber dann geht es bei mir auch nicht. Btw, du musst vorher auch noch andere Commands an den Controller senden. Hier ist ein alter Code für meinen Floppy Treiber, der ist aber glaub ich nen bissle buggy :)

extern void FloppyInterrupt();


int iFloppyReady;
int iFloppy;


void FloppyHandler()
{
    iFloppyReady=1;
}


/* fd_sendbyte() routine from intel manual */
void fd_sendbyte(int byte)
{
    volatile int msr;
    int tmo;

    for (tmo=0; tmo<100; tmo++)
    {
        msr = InByte(0x3F4);
        if( (msr & 0xc0)==0x80 )
        {
            OutByte(0x3F5,byte);
            return;
        }

        InByte(0x80);   /* delay */
    }
}

/* fd_getbyte() routine from intel manual */
int fd_getbyte()
{
    volatile int msr;
    int tmo;

    for (tmo=0; tmo<100; tmo++)
    {
        msr = InByte(0x3F4);
        if ((msr & 0xd0) == 0xd0)
        {
            return InByte(0x3F5);
        }
        InByte(0x80);   /* delay */
    }

    return -1;   /* read timeout */
}


void SetFloppy(int iDriveNum)
{
    iFloppy=iDriveNum;
}

   
void WaitFloppy(int iSense)
{
    if(iSense)
    {
        while(!iFloppyReady);
        iFloppyReady=0;
    }    

    // Read command results
    while(InByte(0x3F4) & 16) fd_getbyte();
   
    if(iSense)
    {
        fd_sendbyte(8);
        fd_getbyte();
        fd_getbyte();
    }
}


void FloppyMotorOn()
{
    int i;
    OutByte(0x3F2,0x1C | iFloppy);
    for(i=0;i<100000;i++);
}


void FloppyMotorOff()
{
    int i;
    OutByte(0x3F2,0x0C | iFloppy);
    for(i=0;i<100000;i++);
}


int FloppySeek(int iTrack)
{
    int i;
   
    FloppyMotorOn();
   
    fd_sendbyte(0x0F);
    fd_sendbyte(0);
    fd_sendbyte(iTrack);
    for(i=0;i<1000000;i++);
    WaitFloppy(1);
   
    FloppyMotorOff();
   
    return 1;
}

   
int ReadFloppy(int iSector,void *pvBuffer)
{
    int head,track,sector;

    // Compute chs address
    sector=(iSector%18)+1;
    track=(iSector/18)/2;
    head=(iSector/18)%2;
   
    // Enable dma channel
    asm("cli");
    OutByte(12,0x46);
    OutByte(11,0x46);
    OutByte(4,(DWORD)pvBuffer & 0xFF); //OFFSET LSB
    OutByte(4,((DWORD)pvBuffer >> 8) & 0xFF); //OFFSET MSB
    OutByte(0x81,(DWORD)pvBuffer >> 16); //PAGE
    OutByte(5,511 & 0xFF); //SIZE-1 LSB
    OutByte(5,511 >> 8); //SIZE-1 MSB
    OutByte(10,2);
     asm("sti");    

    FloppySeek(track);
   
    FloppyMotorOn();

    // Send read command
    fd_sendbyte(0x66);
    fd_sendbyte(head << 2);
    fd_sendbyte(track);
    fd_sendbyte(head);
    fd_sendbyte(sector);
    fd_sendbyte(2);        // bytes per sector
    fd_sendbyte(18);    // Sectors per track
    fd_sendbyte(0x1B);
    fd_sendbyte(0xFF);

    WaitFloppy(0);

    int i;
    for(i=0;i<10000;i++);
    FloppyMotorOff();
   
    return 1;
}

   
void InitFloppy()
{
    int i;
   
    SetFloppy(0);

    iFloppyReady=0;
    SetInterrupt(6,FloppyInterrupt);

    // Reset controller
    OutByte(0x3F2,0);
   
    // Set datarate
    OutByte(0x3F7,0);
   
    // Enable controller
    OutByte(0x3F2,0x0C | iFloppy);
    for(i=0;i<1000000;i++);
    WaitFloppy(1);
   
    // Specifiy
    fd_sendbyte(3);
    fd_sendbyte(0xDF);
    fd_sendbyte(2);

    // Seek
    FloppySeek(1);
   
    // Recalibrate
    FloppyMotorOn();
    fd_sendbyte(7);
    fd_sendbyte(0);
    iFloppyReady=1;
    WaitFloppy(1);
    FloppyMotorOff();
}


MfG GhostCoder
A man, a legend!

MeisterProppa

  • Beiträge: 11
    • Profil anzeigen
    • http://www.alles-flaschen.de
Gespeichert
« Antwort #2 am: 24. June 2004, 13:06 »
Danke, ich werde mir den Code gleich mal näher ansehen und einbauen ;)

MeisterProppa

  • Beiträge: 11
    • Profil anzeigen
    • http://www.alles-flaschen.de
Gespeichert
« Antwort #3 am: 24. June 2004, 17:18 »
Bliebe noch eine Frage.. Was machst du in deinem Interrupt #6 Handler? Du musst ja zumindest irgendwie FloppyReady setzen, da sich das Programm sonst in einer Endlosschleife verfängt. Außerdem muss man einen 0x08 auf Port 0x3F5 schicken und dann zweimal diesen Port lesen.. Gibt es sonst noch was?

GhostCoder

  • Beiträge: 187
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 25. June 2004, 11:37 »
Hiho,

SetInterrupt(6,FloppyInterrupt); installiert den asm Interrupt handler, der wiederrum FloppyHandler() auf. Der Interrupt ist ja nur dazu da, zu signalisierne das etwas beendet worden ist. Und FloppyHandler() setzt iFloppyReady auf true.
Und
while(!iFloppyReady);
iFloppyReady=0;
in WaitFloppy() wartet nun auf den Interrupt. Was mir grad einfällt:
iFloppyReady=0;
while(!iFloppyReady);
wäre besser :)

Das mit dem 0x08 an 0x3F5... Du meinst das "sense interrupt state" command, wa?
Guckst du hier:
    if(iSense)
    {
        fd_sendbyte(8);
        fd_getbyte();
        fd_getbyte();
    }

*gg

MfG GhostCoder
A man, a legend!

 

Einloggen