Autor Thema: Probleme mit dem FDC  (Gelesen 15391 mal)

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« 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
  • von QEMU folgende Meldung:
FLOPPY ERROR: fdctrl_start_transfer: dma_mode=0 direction=1
  • immer "S" zurück
Also 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.
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?

Programm Noob

  • Gast
Gespeichert
« Antwort #1 am: 12. November 2010, 14:34 »
wo gibt es immer "S" zurück?

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #2 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.

Programm Noob

  • Gast
Gespeichert
« Antwort #3 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

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #4 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 mit dem Beispiel Code von OSDev zum DMA (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?

Programm Noob

  • Gast
Gespeichert
« Antwort #5 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.

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #6 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

Programm Noob

  • Gast
Gespeichert
« Antwort #7 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

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #8 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:
  • fat_bios_parameter_block_t
  • fat_directory_entry_t
  • fat_vfat_entry_t
  • fat_rootdir_handle_t
  • fat_res_info_t
Dazu habe ich ein paar Fragen
  • Wie finde ich heraus, was ich gerade gelesen habe?
  • Und wie groß ist ein Sektor in Byte? Oder wird das in einer ganz anderen Einheit gemessen?
  • Welche Sektoren entsprechen welcher Struktur?
  • Wofür wird die fat_res_info_t, die fat_vfat_entry und die fat_rootdir_handle_t benutzt?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #9 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...)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Programm Noob

  • Gast
Gespeichert
« Antwort #10 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

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #11 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.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Programm Noob

  • Gast
Gespeichert
« Antwort #12 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

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #13 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.

Programm Noob

  • Gast
Gespeichert
« Antwort #14 am: 12. November 2010, 19:39 »
Wie gesagt schreibe deinen Code selber.

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #15 am: 13. November 2010, 13:13 »
Genau das habe ich jetzt getan. Ich bin mir allerdings unsicher bei einigen Punkten:
  • Wo fehlen noch welche Wartezeiten?
  • Bei der Lesefunktion habe ich bestimmt irgendeinen Fehler gemacht, weil ich die Anleitung von OSDev.org zu diesem Punkt nicht ganz verstanden habe.
Ich habe diese (http://wiki.osdev.org/Floppy_Disk_Controller) Anleitung benutz. Den Code findet ihr auf http://sesdll1.se.funpic.de/lowlevel/fdc/

S.

Programm Noob

  • Gast
Gespeichert
« Antwort #16 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

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #17 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.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 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.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #19 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.  :?

 

Einloggen