Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: spaceemotion am 12. November 2010, 13:39

Titel: Probleme mit dem FDC
Beitrag von: spaceemotion am 12. November 2010, 13:39
Hallo zusammen,
ich habe ein Problem mit dem FDC. Wenn ich Daten von der Floppy einlesen will, bekomme ich
FLOPPY ERROR: fdctrl_start_transfer: dma_mode=0 direction=1Also Floppyimage habe ich ein einfaches Image ohne Dateisystem genommen, das ich mit echo "TEST" | dd of=floppy.img erstellt habe. Die Lesefunktion stammt von http://forum.osdev.org/viewtopic.php?t=17274 (http://forum.osdev.org/viewtopic.php?t=17274).
floppy.h
/*
  +----------------------------------------------------------------------------------------+
  |                                                                                        |
  |                                     LionOS File                                        |
  |                                                                                        |
  +----------------------------------------------------------------------------------------+
  |                                                                                        |
  |                                        Floppy                                          |
  |                                                                                        |
  +----------------------------------------------------------------------------------------+
*/

#ifndef FLOPPY_H
#define FLOPPY_H

#define NUM_OF_FDD     1
#define NO_ERROR       0
#define ERROR_TIMEOUT  1

#define MSR 0x3F4
#define MSR_MASK_DATAREG 0x80
#define MSR_MASK_DIO2CPU 0x40
#define  CMD 0x3F5
#define MCMD 0x3F2
#define RDSR 0x3F4 //reg dsr
#define RDOR 0x3F2 //Reg dor
#define FLOPPY_MSR_DIO 0x40

#define DSR_SPEED_1MBPS 0x03
#define DSR_SPEED_500KBPS 0x00
#define DSR_SPEED_300KBPS 0x01
#define DSR_SPEED_250KBPS 0x02

#define CMD_WRITE_SECTOR (0x05 | 0x40)
#define CMD_READ_SECTOR (0x06 | 0x40)


#define CMD_SEEK 0x0F
#define FLOPPY_CMD_INT_SENSE 0x08
uint8_t fddDevice;
 
uint8_t error = NO_ERROR;
 
void send_cmd(uint8_t cmd);
void send_data(uint8_t data);
uint8_t read_data();

void initFDD();
void fdHandler(cpu_state *r);
void fddwaitForIRQ();

void resetFDD();
void fddMotor(int state);
void fddChooseDevice(uint8_t id);
int floppy_seek(uint8_t cylinder);
typedef struct fdd
{
int motor;
long la; //lastaccess
int irqRes;
int cylinder;
int head;
int sector;
int size;
uint8_t status;
} fdd;

fdd fd[NUM_OF_FDD];
void floppy_int_sense();
int transfer_sector(uint32_t lba, int write, void* buffer);
int fdc_read(unsigned char *data, unsigned int sector, unsigned int offset, unsigned int length);


#define CHANNEL_ADRESS 0x04
#define CHANNEL_COUNTER 0x05
#define CHANNEL_PAGE 0x81

#include "floppy.c"

#endif

floppy.c
/*
  +----------------------------------------------------------------------------------------+
  |                                                                                        |
  |                                     LionOS File                                        |
  |                                                                                        |
  +----------------------------------------------------------------------------------------+
  |                                                                                        |
  |                                        Floppy                                          |
  |                                                                                        |
  +----------------------------------------------------------------------------------------+
*/

#define CMD_WRITE_SECTOR (0x05 | 0x40)
#define CMD_READ_SECTOR (0x06 | 0x40)



uint8_t read_data()
{
uint8_t timeout;
for(timeout = 0; timeout < 200; timeout++)
{
if( (inb(MSR) & (MSR_MASK_DATAREG | MSR_MASK_DIO2CPU)) == (MSR_MASK_DATAREG | MSR_MASK_DIO2CPU))
{
error = NO_ERROR;
return inb(0x3F5);
}
sleepTicks(5);
}
error = ERROR_TIMEOUT;
return 0;
}
 
 
void send_cmd(uint8_t cmd)
{
send_data(cmd);
}
 
void send_data(uint8_t cmd)
{

fd[fddDevice].la    = getTime();
uint8_t timeout;
for (timeout = 0; timeout < 200; timeout++)
{
if ( (inb(MSR) & (MSR_MASK_DATAREG | MSR_MASK_DIO2CPU)) == MSR_MASK_DATAREG)
{
outb(CMD, cmd);
error = NO_ERROR;
return;
}
sleepTicks(1);  //5ms warten vor dem nächsten Versuch
}
error = ERROR_TIMEOUT;
return;
}
 

/**
  * Positioniert den Lesekopf ueber einen Bestimmten Zylinder.
  *
  * @param cylinder Zylindernummer
  * @return true wenn das Positionieren gelungen ist, sonst false
  */
int floppy_seek(uint8_t cylinder)
{
DEBUG_MSG("Kopf neu positionieren");
if(fd[fddDevice].cylinder == cylinder)
{
DEBUG_MSG("    Steht bereits richtig");
return true;
}


//floppy_set_motor(true);

//floppy_clr_irqcnt();

send_cmd(CMD_SEEK);
send_cmd(fddDevice);
send_cmd(cylinder);

/*if(floppy_wait_irq(1) == false)
{
return false;
}*/

floppy_int_sense();

sleepTicks(1);

while (inb(MSR) & 0x0F) {
DEBUG_MSG("Laufwerk ist noch beschaeftigt");
sleepTicks(1);
}

if (fd[fddDevice].cylinder != cylinder) {
DEBUG_MSG("Warnung: Floppy steht nach SEEK(%d) auf %d",
cylinder, fd[fddDevice].cylinder);
}

if(fd[fddDevice].status != 0x20)
{   
DEBUG_MSG("    false");
return false;
}
else
{
DEBUG_MSG("    true");
return true;
}
return true;
}



void fdHandler(cpu_state *r)
{
DEBUG_MSG("FDD Int!");
fd[fddDevice].irqRes++;
}

void resetFDD()
{
outb(MCMD, 0);
fddMotor(false);
}

void fddChooseDevice(uint8_t id)
{
fddDevice = id;
uint8_t tmp = inb(MCMD);
outb(MCMD, (tmp & (~0x03)) | fddDevice);
}

void fddMotor(int state)
{
fd[fddDevice].motor = state;
fd[fddDevice].la    = getTime();
uint8_t status = inb(MCMD);
//DEBUG_MSG("FDD: State: %d", status);
if (state==true)
{
outb(MCMD, (status & 0x0F) | (0x10 << fddDevice));
}
else
{
//DEBUG_MSG("FDD: Change state from %d to %d", status, status & ~(0x10 << id));
outb(MCMD, status & ~(0x10 << fddDevice));
}

sleepTicks(5);
//Hier muss eine Sleep funktion rein!!!!
//sleepTicks(10);
}

void fddwaitForIRQ()
{
int i = fd[fddDevice].irqRes;
DEBUG_MSG("Wait for IRQ6: Arrived IRQ: %d", i);
while(1)
{
asm("nop");
if (i == fd[fddDevice].irqRes-1)
{
return;
}
}
}

/**
 * Kalibriert das Laufwerk
 *
 * @return true wenn das Neukalibrieren gelungen ist, sonst false
 */
int FDDrecalibrate(void)
{
    DEBUG_MSG("Kalibriere Laufwerk neu");
fd[fddDevice].cylinder = 255;
fddMotor(true);

int i = 0;
while ((i < 5) && (fd[fddDevice].cylinder != 0))
{
//floppy_clr_irqcnt();
send_cmd(0x07);
send_cmd(fddDevice);
//floppy_wait_irq(1);
//fddwaitForIRQ();
//FIXME Wait for IRQ Here!!!!
//loppy_int_sense();
++i;
}
return (i < 5);
}




/**
 * Mir ist nicht bekannt, was diese Funktion genau macht. Sie schein aber
 * notwendig zu sein.
 */
void floppy_int_sense()
{
send_cmd(FLOPPY_CMD_INT_SENSE);
fd[fddDevice].status = read_data();
fd[fddDevice].cylinder = read_data();
}

void initFDD()
{
// asm("sti");
//int i;

fddChooseDevice(0);
uint8_t fdd = cmos_read(0x10);


uint8_t fd1 = fdd & 0xF;
uint8_t fd0 = (fdd & 0xF0) >> 4;

DEBUG_MSG("CMOS Floppy == %d\nfd0 == %d, fd1 == %d", fdd, fd0, fd1);

if (!(fd0 | fd1))
{ return; }

if(fd0==0)
{
DEBUG_MSG("No floppy 0!");
//return;
}
else
{
fddChooseDevice(0);
if(fd0==1)
{
DEBUG_MSG("Floppy 0 found... Size = 360 kB");
}
else if(fd0==2)
{
DEBUG_MSG("Floppy 0 found... Size = 1.2 MB");
}
else if(fd0==3)
{
DEBUG_MSG("Floppy 0 found... Size = 720 kB");
}
else if(fd0==4)
{
DEBUG_MSG("Floppy 0 found... Size = 1.44 MB");
}
}

if(fd1==0)
{
DEBUG_MSG("No floppy 1!");
//return;
}
else if(fd1==1)
{
DEBUG_MSG("Floppy 1 found... Size = 360 kB");
}
else if(fd1==2)
{
DEBUG_MSG("Floppy 1 found... Size = 1.2 MB");
}
else if(fd1==3)
{
DEBUG_MSG("Floppy 1 found... Size = 720 kB");
}
else if(fd1==4)
{
DEBUG_MSG("Floppy 1 found... Size = 1.44 MB");
}
/*
0000b = Laufwerk nicht vorhanden
0001b = 5 1/4 - 360 kB
0010b = 5 1/4 - 1.2 MB
0011b = 3 1/2 - 720 kB
0100b = 3 1/2 - 1.44 MB (sollte eigentlich heutzutage der Standard sein)
0101b - 1111b sind unbenutzt

*/

irq_install_handler(6, fdHandler);

resetFDD();
fd[fddDevice].irqRes = 0;

outb(RDSR, DSR_SPEED_500KBPS);
outb(RDOR, 0x0C);
//fddwaitForIRQ();
//FIXME Wait for IRQ here!!!
FDDrecalibrate();

DEBUG_MSG("Test");
//TEST
//int x;

//uint32_t lba = 109;

//int transfer_sector(uint8_t cylinder, uint8_t head, uint8_t sector, int write, void* buffer)
//if ( transfer_sector(lba, 0, (void *) &x) )
//{
// DEBUG_MSG("%d",x);
//}
//sleepTicks(20);
//resetFDD();
//char c = 'A';
//transfer_sector(109, 1, (void *) &c);

unsigned char c = 'A';
unsigned char *test = &c;
fdc_read(test, 0,0,1);
DEBUG_MSG("Readed: >%c<", *test);
}







int fdc_read(unsigned char *data, unsigned int sector, unsigned int offset, unsigned int length)
{
unsigned char st0, st1, st2, rcy, rhe, rse, bps;//, cyl;

fddMotor(true);


if(!floppy_seek(sector))
{
DEBUG_MSG(" failed seek! ");
return 0;
}

//send the read command
send_cmd(CMD_READ_SECTOR );
send_data( fddDevice | (fd->head << 2));   //head and drive
send_data( fd->cylinder);
send_data( fd->head);
send_data( fd->sector);
send_data( 2);                  // bytes per sector (2 = 512)
send_data( 1);   // "end of track" the final sector of this track (I have no idea what it does)
send_data( 0x1B);               //GAP3 length
send_data( 0xFF);               //data length (0xFF because bytes per sector != 0)

//get the data
//fddwaitForIRQ();//wait for it...
//GO!
int i = 0; unsigned char *tmp = data;
for(i = 0; i < 512; i++)
{   
*tmp = (unsigned char) read_data();
//write_hex(*tmp);

tmp++;
}

// read status information
st0 = read_data();
//write_hex(st0);
st1 = read_data();
st2 = read_data();
/*
* These are cylinder/head/sector values, updated with some
* rather bizarre logic, that I would like to understand.
*/
rcy = read_data();
rhe = read_data();
rse = read_data();
// bytes per sector, should be what we programmed in
bps = read_data();

fddMotor(false);

return 1;
}
Hat jemand eine Idee?
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 14:34
wo gibt es immer "S" zurück?
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 12. November 2010, 14:56
DEBUG_MSG("Readed: >%c<", *test); schreibt:
Zitat
Readed: >S<
Für mich heißt das, dass fdc_read in den Buffer 83 oder S schreibt.
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 16:08
probier mal den Code ausm Wiki bzw schreibe eigenen. oftmals stehen in Foren Threads nicht funktionierender Code, eben weil er nicht geht. nur mit kopieren wirst du nicht weit kommen. bei gezielten Fragen, können wir dir  gerne helfen.
Und wie groß ist das image was du ließt?

PNoob
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 12. November 2010, 16:32
Da hast du natürlich Recht. Also noch mal von vorne:
Ich habe den Code vom http://www.lowlevel.eu/wiki/FDC#Sektoren_lesen.2Fschreiben (http://www.lowlevel.eu/wiki/FDC#Sektoren_lesen.2Fschreiben) mit dem Beispiel Code von OSDev zum DMA (http://wiki.osdev.org/DMA#Floppy_Disk_DMA_Initialization (http://wiki.osdev.org/DMA#Floppy_Disk_DMA_Initialization)) verbunden und leicht modifiziert. Außerdem sind die Formeln und Paramter um aus LBA zu CHS zu kommen aus tyndur. Mein Floppy Image ist mit dd if=/dev/zero of=floppy.img bs=1024 count=1440
mkdosfs -I floppy.img
erstellt worden und ist demnach 1,44 MB groß. Der Kernel wird über QEMU mit
qemu -m 526 -kernel .core/kernel.krn -initrd test/test.elf
gestartet, wobei das Module zu vernachlässigen wäre.
Ich starte aus der FDDinit den Lesevorgang mit
char x[5];
if ( transfer_sector(0, 0, (void *) &x, 5 ))
{
DEBUG_MSG("%s",x);
}
Die VM scheitert nach 5 Fehlversuchen. Hier die Funktion:
int transfer_sector(uint32_t LBA, int write, void* buffer, size_t size)
{

uint8_t C =   LBA  /  (MH*MS);
uint8_t H =  (LBA % (MH*MS))  /  MS;
uint8_t S = ((LBA % (MH*MS)) % MS) + 1;


fddMotor(true);
floppy_seek(C);

//dma_begin_transfer(buffer, write);
/*
; set DMA channel 2 to transfer data from 0x1000 - 0x33ff in memory
; paging must map this _physical_ memory elsewhere and _pin_ it from paging to disk!
; set the counter to 0x23ff, the length of a track on a 1.44 MiB floppy - 1 (assuming 512 byte sectors)
; transfer length = counter + 1
out 0x0a, 0x05      ; mask DMA channel 2 and 0
out 0x0c, 0xFF      ; reset the master flip-flop
out 0x04, 0         ; address to 0 (low byte)
out 0x04, 0x10      ; address to 0x10 (high byte)
out 0x0c, 0xFF      ; reset the master flip-flop (again!!!)
out 0x05, 0xFF      ; count to 0x23ff (low byte)
out 0x05, 0x23      ; count to 0x23ff (high byte),
out 0x81, 0         ; external page register to 0 for total address of 00 10 00
out 0x0a, 0x01      ; unmask DMA channel 2
ret

*/



outb( 0x0A,        0x05        ); // mask DMA Channel 2 And 0
outb( 0x0C,        0xFF        ); // reset the master flip-flop
outb( 0x04, (long) buffer&0xFF ); // address to 0 (low byte)
outb( 0x04, (long) buffer >> 8 ); // address to 0x10 (high byte)
outb( 0x0C,        0xFF        ); // reset the master flip-flop (again!!!)
outb( 0x05,   size&0xFF        ); // count to 0x23ff (low byte)
outb( 0x05,   size >> 8        ); // count to 0x23ff (high byte),
outb( 0x81,        0           ); // external page register to 0 for total address of 00 10 00
outb( 0x0A,        0x01        ); // unmask DMA channel 2

if (write)
{}
else
{
outb( 0x0A, 0x05); // mask DMA channel 2 and 0
outb( 0x0B, 0x56); // 01010110
   // single transfer, address increment, autoinit, read, channel2)
outb( 0x0A, 0x01); // unmask DMA channel 2

}


int i;
for (i = 0; i<5; i++)
{
send_cmd(write ? CMD_WRITE_SECTOR : CMD_READ_SECTOR);
send_data(fddDevice | H<<2);
send_data(C);
send_data(H);
send_data(S);
send_data(2);
send_data(18);
send_data(27);
send_data(0xFF);
//wait_irq(); FIXME On a real PC this must happend
read_data();  //st0
read_data();  //st1
read_data();  //st2
read_data();  //cylinder
read_data();  //head
read_data();  //sector
read_data();  //Sektorgröße
if ( inb(MSR) & 0xC0)
{
//check_interrupt_status();
return true;
}
}
/* fünf Fehlversuche */
return false;
}


Was muss ich tun, damit mein Code funktioniert?
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 16:34
guck dir mal die Komandozeile von Qemu an... ;) und überlege dir woher qemu weiß das es nen Disetten laufwerk hat und welche Dikette/Image wer verwenden soll.
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 12. November 2010, 16:40
So sorry, aber das ist nicht der Grund. Ich habe versendlich aus meinem Shell Skript die falsche Zeile genommen.  :-D
Die richte Zeile:
qemu -m 526 -kernel .core/kernel.krn -initrd $2/$2.elf -fda floppy.img
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 16:46
Da du das Image ja formatierst, steht da ja nicht nur null. aund wenn du die Zahlen die da stehen als String, also als ASCII Zeichen ausgibst, ist das klar, das da buchstaben bei rauskommen. leg dir ne Struct an, wo du den BPB von FAT12 drin abbildest und lege die auf den Buffer. Dann gib daraus einige Werte aus und vergleiche die, mit denen die da normal sein dürften.

PNoob
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 12. November 2010, 17:17
Weil ich keine Ahnung habe, wie diese struct aussehen soll, habe ich gerade bei tyndur mal geschaut. Es gibt dort mehrer Structs zum Thema:
Dazu habe ich ein paar Fragen
Titel: Re:Probleme mit dem FDC
Beitrag von: kevin am 12. November 2010, 18:44
Lass das mit FAT interpretieren am besten erstmal bleiben, bevor du nicht einen Floppytreiber hast, der tut.

Wenn du schauen willst, was wirklich rauskommen müsste, schau dir das Floppyimage mit hexdump oder irgendeinem Hexeditor an. (Ein S ist das bei mir aber trotzdem nicht...)
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 18:52
@taljeth das mit der Struct habe ich damals auch zum testen benutzt. danach habe ich aber auch erstmal nen unformatiertes Image benutzt und nun baue ich den FAT Treibern.

@spacemotion: Ließ dir bevor du fragst mal die Artikel zu FAT und EXT durch. Die Wikipedia Artikel dazu sind auch sehr informativ. Da werden dir alle fragen beantwortet. Wenn du dazu dann noch fragen hast, dann frag. wofür die ganzen stuct bei Tyndur sind, solltest du dann auch selber herrausfinden können, wobei ich dir empfehlen würde sich den code(den FAT Code) ncht zusehr anzusehen. ich habe da meine Probleme mit da ne logig reinzudenken.

PNoob
Titel: Re:Probleme mit dem FDC
Beitrag von: kevin am 12. November 2010, 18:54
@taljeth das mit der Struct habe ich damals auch zum testen benutzt.…
Das muss ja aber nicht jeder so umständlich machen, nur weil du dir nicht besser zu helfen wusstest.

Zitat
@spacemotion: Ließ dir bevor du fragst mal die Artikel zu FAT und EXT durch. Die Wikipedia Artikel dazu sind auch sehr informativ. Da werden dir alle fragen beantwortet. Wenn du dazu dann noch fragen hast, dann frag. wofür die ganzen stuct bei Tyndur sind, solltest du dann auch selber herrausfinden können, wobei ich dir empfehlen würde sich den code(den FAT Code) ncht zusehr anzusehen. ich habe da meine Probleme mit da ne logig reinzudenken.
Doku lesen ist fast immer einfacher als Code lesen, aber das ist nichts neues.

Falls es übrigens in Vergessenheit geraten ist: In diesem Thread geht es gar nicht um Dateisysteme, sondern einfach nur um Floppy.
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 19:03
klar man kann auch einfach ein Byte lesen und ausgeben und sich met nem Hexeditor ansehen ob das ausgegebene ach wirklich da steht.

PNoob
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 12. November 2010, 19:32
Könnte man das Problem nicht umdrehen? Also statt lesen was an LBA ... steht, an LBA ... etwas schreiben? Dann könnte man mit hexdump und/oder dd gucken, ob es funktioniert hat.
Geht das? Wenn ja, wie? Ich hab das jetzt gerade so:
int transfer_sector(uint32_t LBA, int write, void* buffer, size_t size)
{

uint8_t C =   LBA  /  (MH*MS);
uint8_t H =  (LBA % (MH*MS))  /  MS;
uint8_t S = ((LBA % (MH*MS)) % MS) + 1;


fddMotor(true);
floppy_seek(C);

//dma_begin_transfer(buffer, write);
/*
; set DMA channel 2 to transfer data from 0x1000 - 0x33ff in memory
; paging must map this _physical_ memory elsewhere and _pin_ it from paging to disk!
; set the counter to 0x23ff, the length of a track on a 1.44 MiB floppy - 1 (assuming 512 byte sectors)
; transfer length = counter + 1
out 0x0a, 0x05      ; mask DMA channel 2 and 0
out 0x0c, 0xFF      ; reset the master flip-flop
out 0x04, 0         ; address to 0 (low byte)
out 0x04, 0x10      ; address to 0x10 (high byte)
out 0x0c, 0xFF      ; reset the master flip-flop (again!!!)
out 0x05, 0xFF      ; count to 0x23ff (low byte)
out 0x05, 0x23      ; count to 0x23ff (high byte),
out 0x81, 0         ; external page register to 0 for total address of 00 10 00
out 0x0a, 0x01      ; unmask DMA channel 2
ret

*/



outb( 0x0A,        0x05        ); // mask DMA Channel 2 And 0
outb( 0x0C,        0xFF        ); // reset the master flip-flop
outb( 0x04, (long) buffer&0xFF ); // address to 0 (low byte)
outb( 0x04, (long) buffer >> 8 ); // address to 0x10 (high byte)
outb( 0x0C,        0xFF        ); // reset the master flip-flop (again!!!)
outb( 0x05,   size&0xFF        ); // count to 0x23ff (low byte)
outb( 0x05,   size >> 8        ); // count to 0x23ff (high byte),
outb( 0x81,        0           ); // external page register to 0 for total address of 00 10 00
outb( 0x0A,        0x01        ); // unmask DMA channel 2

if (write)
{
outb( 0x0a, 0x05 )     ; //mask DMA channel 2 and 0
outb( 0x0b, 0x5A )     ; //01011010
; //single transfer, address increment, autoinit, write, channel2)
outb( 0x0a, 0x01 )     ; //unmask DMA channel 2

}
else
{
outb( 0x0A, 0x05); // mask DMA channel 2 and 0
outb( 0x0B, 0x56); // 01010110
   // single transfer, address increment, autoinit, read, channel2)
outb( 0x0A, 0x01); // unmask DMA channel 2

}


int i;
for (i = 0; i<5; i++)
{
send_cmd(write ? CMD_WRITE_SECTOR : CMD_READ_SECTOR);
send_data(fddDevice | H<<2);
send_data(C);
send_data(H);
send_data(S);
send_data(2);
send_data(18);
send_data(27);
send_data(0xFF);
//wait_irq(); FIXME On a real PC this must happend
sleepTicks(2);
read_data();  //st0
read_data();  //st1
read_data();  //st2
read_data();  //cylinder
read_data();  //head
read_data();  //sector
read_data();  //Sektorgröße
if ( inb(MSR) & 0xC0)
{
//check_interrupt_status();
return true;
fddMotor(false);
}
}
/* fünf Fehlversuche */
return false;
}

Ich bekomme zwar keine Fehlermeldung, aber hexdump sagt vor und nach dem Start von meinem OS:
hexdump floppy.img
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
00b4000

S.
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 12. November 2010, 19:39
Wie gesagt schreibe deinen Code selber.
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 13. November 2010, 13:13
Genau das habe ich jetzt getan. Ich bin mir allerdings unsicher bei einigen Punkten:
Ich habe diese (http://wiki.osdev.org/Floppy_Disk_Controller (http://wiki.osdev.org/Floppy_Disk_Controller)) Anleitung benutz. Den Code findet ihr auf http://sesdll1.se.funpic.de/lowlevel/fdc/ (http://sesdll1.se.funpic.de/lowlevel/fdc/)

S.
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 13. November 2010, 23:41
Also als Lektüre kann ich dir den FDC Artikel im Hauseigenem Wiki nennen. die ist sehr gut und dort werden auch Wartezeiten beschrieben. ansonsten nondot ist auch ein egute Anlaufstelle für solche älteren Bauteile.

Wegen deiner Lesefunktion, hast du die gestestet? was geht, was geht nicht?

PNoob
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 14. November 2010, 08:24
Ja, die Funktion habe ich getestet. Das Programm kommt bis zur Executionphase der Schreibfunktion, wo ich auch den Fehler vermute. QEMU meckert rum: FLOPPY ERROR: fdctrl_start_transfer: dma_mode=0 direction=1. Die Executionphase war auch der Teil den ich am schlechtesten verstanden habe. Code wieder auch oben genanntem Link. Ich wollte die ganze Aktion ohne DMA machen, weil mit PIO einfacher erschien.

S.
Titel: Re:Probleme mit dem FDC
Beitrag von: kevin am 14. November 2010, 10:02
Kurzer Blick in den qemu-Code verrät, dass der Code innerhalb eines if (fdctrl->dor & FD_DOR_DMAEN) steht. Vermutlich solltest du dieses Bit nicht setzen, wenn du kein DMA machen willst.
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 14. November 2010, 11:29
Oh, ja. Sorry. Ich hatte in der Funktion wohl ein falsches Bitflag. Das hab ich jetzt behoben. Jetzt bekomme ich von QEMU diese Meldung: FLOPPY ERROR: fdctrl_unimplemented: unimplemented command 0x96Also sende ich ein Befehl ab, den es nicht gibt, aber das mache ich eigentlich garnicht. Hier der Codeauszug:
void sendPara( uint8_t para )
{
while( (inb( MSR) & 0xC0) != 0x80 ); //MSR = 0x3F4
outb( DATA_FIFO, para );  //DATA_FIFO = 0x3F5
}
...
uint8_t cmd = (0x05 | 0x40);
outb(DATA_FIFO, cmd );
sendPara( fdc.acDrive | (H << 2) ); //H = head, fdc.acDrive = aktueller Drive
sendPara( C ); //Cylinder
sendPara( H );
sendPara( S ); //Sektor
sendPara( 2 );
sendPara( (int) size/512. );
sendPara( 0x1B );
sendPara( 0xFF )

Der Fehler liegt in der ersten Parameterübergabe, also hier: sendPara( fdc.acDrive | (H << 2) ); Qemu sagt mir ja, dass ich 0x96 sende, ich weiß aber nicht wo.  :?
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 14. November 2010, 12:18
bist du dir sicher das der Fehler da auftritt? Weil ich sehe da auch kein 0x96.
@taljeth : oder könnte das nen Fehler in qemu sein?
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 14. November 2010, 12:57
Als ich den die Zeile auskommentiert und eine while(1); danach eingebaut. Der Fehler trat nicht mehr auf. Also hat er etwas mit dem sendPara() zu tun.
taljhet hat allerdings recht, was seine "Fehlerdifinition" angeht.

S.
Titel: Re:Probleme mit dem FDC
Beitrag von: MNemo am 14. November 2010, 17:12
Als ich den die Zeile auskommentiert und eine while(1); danach eingebaut. Der Fehler trat nicht mehr auf. Also hat er etwas mit dem sendPara() zu tun.

Hmm… ich weiß jetzt nicht genau wo du das "while" hingesetzt hast, aber wenn mit 'while' kein Fehler Auftritt dann liegt der Fehler eindeutig hinter dem 'while', das ist dir aber wahrscheinlich klar und du hast dich nur nicht genau ausgedrückt.

Zu deinem code:
Wo der Wiki-Code 'send_cmd' benutzt, benutzt du 'out', auch wenn das bei QEMU vermutlich nichts ausmachen sollte, könnte das spätestens bei echter HW zu Problemen fuhren wenn du nicht wartest bis der FDC bereit ist.
Titel: Re:Probleme mit dem FDC
Beitrag von: kevin am 14. November 2010, 17:16
Qemu sagt mir ja, dass ich 0x96 sende, ich weiß aber nicht wo.  :?
Dann bau ein paar kprintfs ein, bis du es weißt.

@taljeth : oder könnte das nen Fehler in qemu sein?
Nein, der Compiler und der Emulator haben immer recht. *

*) Die einzige Ausnahme, für die das nicht gilt, sind Leute, die genau wissen, was sie tun
Titel: Re:Probleme mit dem FDC
Beitrag von: Programm Noob am 14. November 2010, 17:55
@taljeth : oder könnte das nen Fehler in qemu sein?
Nein, der Compiler und der Emulator haben immer recht. *

*) Die einzige Ausnahme, für die das nicht gilt, sind Leute, die genau wissen, was sie tun
Hätte ja sein können, das das nen Bug in Qemu ist.

PNoob
Titel: Re:Probleme mit dem FDC
Beitrag von: erik.vikinger am 15. November 2010, 10:11
Hallo,

Die einzige Ausnahme, für die das nicht gilt, sind Leute, die genau wissen, was sie tun
Mit anderen Worten: es gibt hier keine Ausnahmen von der Regel. ;)

SCNR
Erik
Titel: Re:Probleme mit dem FDC
Beitrag von: kevin am 15. November 2010, 10:36
*hust*

Vielleicht wäre s/genau/so ungefähr/ korrekter, aber dann bestünde die Gefahr, dass PNoob das auf sich bezieht, obwohl das definitiv nicht so gemeint ist. ;)
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 15. November 2010, 15:15
Als ich den die Zeile auskommentiert und eine while(1); danach eingebaut. Der Fehler trat nicht mehr auf. Also hat er etwas mit dem sendPara() zu tun.

Hmm… ich weiß jetzt nicht genau wo du das "while" hingesetzt hast, aber wenn mit 'while' kein Fehler Auftritt dann liegt der Fehler eindeutig hinter dem 'while', das ist dir aber wahrscheinlich klar und du hast dich nur nicht genau ausgedrückt.

Zu deinem code: 
Wo der Wiki-Code 'send_cmd' benutzt, benutzt du 'out', auch wenn das bei QEMU vermutlich nichts ausmachen sollte, könnte das spätestens bei echter HW zu Problemen fuhren wenn du nicht wartest bis der FDC bereit ist.
Ich glaube, dass ich hier ein paar Missverständnisse beseitigen muss:
....
//sendPara( fdc.acDrive | (H << 2) ); //H = head, fdc.acDrive = aktueller Drive
while(1);
So tritt kein Fehle auf.

S.
Titel: Re:Probleme mit dem FDC
Beitrag von: MNemo am 15. November 2010, 18:24
outb ist eine ganz Normale Funktion um einen Wert in einen Port zu schreiben
Das ist mir klar. Ich kenne die Spezifikation nicht, aber einfach so werte raus hauen scheint
mir bei dem, was im Wiki als Code steht, nicht angebracht.

Zitat
Das while(1); ab ich wie folgt positioniert:
....
//sendPara( fdc.acDrive | (H << 2) ); //H = head, fdc.acDrive = aktueller Drive
while(1);
So tritt kein Fehle auf.
Also doch :roll:. Wer sagt dir denn, dass der Fehler nicht sonst erst hinter dem while auftrit?
Entweder auskommentieren, oder while. So kannst du auch gleich das while vorne dran setzen.

while und fehler => fehler vor while
while und kein fehler => kein fehler vor while

Wenn du den potentiellen fehler code auskommentierst kannst du also gar nicht mehr sagen, ob er fehler frei ist.
Titel: Re:Probleme mit dem FDC
Beitrag von: spaceemotion am 19. November 2010, 14:46
Wie auch immer. Ich hab den Code neu geschrieben und er funktioniert.

S.