Using floppy disc

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Re:Using floppy disc

Post by Neo »

i think your FDC_cmd_ready() is wrong and so is mine (the C one I shown). I've corrected mine above and yours could be written as shown here

Code: Select all

void FDC_cmd_ready(unsigned char code)
{
  while( (in(0x3F4)&0xC0)!=code );
}
BTW the "reset" only involves the

Code: Select all

out(0x3F2,0);
out(0x3F2,0x0C);
fdc_flag=0;
actually what you are doing is trying to initialize the FDC.(There's nothing wrong with naming the function reset() though).
Incidentally i see that you've not set the 'fdc_flag' value anywhere in the code you've shown, how will you know if an IRQ has occured without this?
Only Human
Brandon

Re:Using floppy disc

Post by Brandon »

Yeah I changed the "ready" functions...

I set the fdc_flag in my IRQ handler

Code: Select all

void int_38(void)
{
???fdc_flag = 1;
}
the problem has to be in my reset function (the last parts with issueing the command 4 times and send the specify command)

This is ALL my FDC code (except for the ISR written in asm, that will call the int_38(look above) method:

Code: Select all

/* Reset and initialize the fdc */
void reset_floppy() {
???fdc_flag = 0;
???// Reset the floppy
???out(0x3f2, 0);
???out(0x3f2, 0x0C);

???// Set the data rate = 500 kbps
???out(0x3f7, 0);

???wait_for_floppy_irq();???// Wait for IRC

???int i;
???for(i = 0;i<4;i++) {
        ???send_floppy_command(0x8);  // Send the check interrupt cmd
        ???get_floppy_command();      // Read the data reg
        ???get_floppy_command();      // Read the data reg
        }

        send_floppy_command(3);??????// The specify command
        send_floppy_command(0);         // And the arguments
        send_floppy_command(0);
}

/* Wait until we can send a command */
void FDC_cmd_write_ready() {
???while((in(0x3F4) & 0x80) != 0x80);
}

/* Wait untill we can read the result */
void FDC_cmd_read_ready() {
???while((in(0x3F4) & 0xC0) != 0xC0);
}

/* Wait for a floppy IRQ to fire */
void wait_for_floppy_irq() {
???for(;;)
??????if(fdc_flag != 0) {
?????????fdc_flag = 0;
?????????return;
??????}
}

/* Send a command */
void send_floppy_command(unsigned char command) {
???FDC_cmd_write_ready();
???out(0x3f5, command);
}

/* Read a result */
unsigned char get_floppy_command() {
???FDC_cmd_read_ready();
???return in(0x3f5);
}

/* Start the motor */
void start_floppy_motor() {
???out(0x3f2, 0x1C);
}
In the main method, I got something like this:

Code: Select all

unmask_irq(FLOPPY_IRQ);
reset_floppy();
print("Floppy reseted\n", RED_TXT); // This gets printed

start_floppy_motor();
wait_for_floppy_irq();  // Never ends
For some reason the last floppy IRQ never fires (which it should cause I start the motor), so I guess Im doing something wrong in the initialization...been stuck with this stupid problem for days :(
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Using floppy disc

Post by Brendan »

Hi,
Brandon wrote: For some reason the last floppy IRQ never fires (which it should cause I start the motor), so I guess Im doing something wrong in the initialization...been stuck with this stupid problem for days :(
Starting the floppy motor will not cause an IRQ. This should work properly:

Code: Select all

unmask_irq(FLOPPY_IRQ);
reset_floppy();
print("Floppy reseted\n", RED_TXT);

start_floppy_motor();
Please note that "reset_floppy()" does not reset one of the 4 floppy/tape devices, but instead resets the floppy disk controller.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Re:Using floppy disc

Post by Neo »

The arguments for the "Specify" command are wrong, i dont think they can be 0. try 0xAF for the 'SRT & HUT' and 0x02 for the 'HLT and NDMA'
(these are the bios default values on my comp)
so the specify part should be

Code: Select all

send_floppy_command(3);      // The specify command
send_floppy_command(0xAF);        // And the arguments
send_floppy_command(0x02);
Your wait_for_floppy_irq() code could also be made simpler

Code: Select all

/* Wait for a floppy IRQ to fire */
void wait_for_floppy_irq() {
  while(!fdc_flag); // wait for the int38() to change it to 1
}
in fact you could just use that one line instead of a function.

The start motor function should also have a delay after starting

Code: Select all

/* Start the motor */
void start_floppy_motor() {
   out(0x3f2, 0x1C);
   delay(500);   // 500 ms delay
}
although i think it may work without this.
Only Human
Brandon

Re:Using floppy disc

Post by Brandon »

Alright, thank you!

Brendan: Are u sure that starting the motor wont fire an IRQ?

Is there anything else I have to do to "configure" the fdc? When I?ve ran the reset function, is there any way of testing that everything went ok during the initialization?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Using floppy disc

Post by Brendan »

Hi,
Brandon wrote: Brendan: Are u sure that starting the motor wont fire an IRQ?
Yes :) It's almost as if the bits in the DOR are directly connected to the floppy motors and nothing else.
Brandon wrote: Is there anything else I have to do to "configure" the fdc? When I?ve ran the reset function, is there any way of testing that everything went ok during the initialization?
It depends on your OS and what sort of quality you want. You could try to detect which devices are connected (1200 Kb, 1440 Kb, 2880 Kb, tape, etc). You could also detect which floppy controllers are present (ie. first FDC at base IO port 0x03F0, second FDC at 0x0370), and what type they are (see the "version" command 0x10). Then there's the question of how many devices you'd support - the basic FDC chip handles 4 devices, while most motherboards/cards are only capable of handling 2 of them. In theory you could have 4 devices on the primary FDC, another 4 on the secondary FDC (for 8 devices).

Then there's the question of how your OS will handle all this. Some OSs have a single floppy disk driver, while on others you'd have a device driver for each floppy drive controller chip, and seperate drivers for each device.

Reseting a floppy drive device would include the "recalibrate" command, detecting if any media is in the drive and trying to figure out what type of media is inserted (and configuring for that media). Media specific configuration includes the "specify" command 0x03, the data rate, any device driver data (buffers, etc), and any OS specific stuff (for e.g. mounting it at "/dev/fda0").

The most annoying thing is there's no decent way of determining what media is in a device. DOS use the BPB (BIOS Parameter Block) in the first sector, but this is badly named and should be called the DPB (DOS Parameter Block) as it's not required, and not suitable for some of the floppy formats you could create (for e.g. if you use a higher number of sectors per track on the outer cyclinders).

In general I set the data rate to 1 Mb/s and try to read the first sector of the disk. If this doesn't work (or if 1 Mb/s isn't supported) I try 500 Kb/s, then 300 Kb/s, then 250 Kb/s. Sooner or later one of the data rates will work. Then you can try different numbers of sectors per track and/or different numbers of bytes per sector, and/or figure out the highest track number. The more floppy disk formats your OS will handle the harder this will be, which is why a lot of hobby OSs only support 1440 Kb.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Brandon

Re:Using floppy disc

Post by Brandon »

Alright thanks ;D
Is it difficult to read / write data to the floppy? I know you can do it with DMA but I also read that you can read each byte from a port? (Right now I dont care if it?s slow, I just want to get a filesystem working)
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Using floppy disc

Post by Brendan »

Hi,
Brandon wrote: Alright thanks ;D
Is it difficult to read / write data to the floppy? I know you can do it with DMA but I also read that you can read each byte from a port? (Right now I dont care if it?s slow, I just want to get a filesystem working)
It's not too difficult once it setup properly - just issue the command and transfer data.

You can read (or write) each byte to a port, but I think you get an IRQ for each byte. I also think the transfer takes just as long regardless of how you do it (but handling all those IRQs will slow down anything else the CPU is trying to do).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Brandon

Re:Using floppy disc

Post by Brandon »

Hehe well is it difficult to set it up? Wish there was tutorials on this kind of stuff :) I cant find anything anywhere
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Using floppy disc

Post by Brendan »

Hi,
Brandon wrote: Hehe well is it difficult to set it up? Wish there was tutorials on this kind of stuff :) I cant find anything anywhere
I meant "it's not too difficult once the floppy controller and floppy disk drive are setup".

To setup a floppy transfer you'd:
- set the data rate (if it's not already set)
- convert the logical address into CHS
- turn the motor on (if it's not already on)
- give the motor time to reach operating speed (if it wasn't already on)
- do a "seek" and wait for the heads to settle (if it's not already at the right track)
- setup the DMA transfer (if you're using DMA)
- send the command and it's parameters
- wait for an IRQ saying the DMA transfer is done (if using DMA) or wait for an IRQ saying the next byte is ready, transfer the byte and wait for the next IRQ (512 times if you're using 512 byte sectors)
- if an operation on a different floppy drive is next turn this floppy drive motor off and switch to other drive, otherwise if there are no more operations for this drive set the "motor off" delay, and if no more operations arrive for this drive before the delay expires turn the floppy motor off.

I've omitted all error checking/error handling and caching for simplicity. Of course different floppy device drivers may do things differently.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Brandon

Re:Using floppy disc

Post by Brandon »

Thank you very much dude! I?ll try it :)

u know everything, dont u :D
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Re:Using floppy disc

Post by Neo »

try searching www.osdever.net

Try executing the "Recalibrate" command (0x07) to see if you get an IRQ. You have to send the command followed by the drive no. (0 for first one) and then wait for an INT to be generated. After which you should 'Check int Status'.

BTW what about checking the values you get when you execute the commands? they contain values which tell you what may be wrong. You seem to be just reading the values but not checking them or at least printing them out. I'm referring to your

Code: Select all

for(i = 0;i<4;i++) {
  send_floppy_command(0x8);  // Send the check interrupt cmd
  get_floppy_command();      // Read the data reg /* print this out*/
  get_floppy_command();      // Read the data reg
}
Only Human
Brandon

Re:Using floppy disc

Post by Brandon »

I think it works to callibrate it, I get an IRQ and a correct result phase. Then I try a simple seek (0xF) and I think it works, I send 0xF and the "arguments" and then I get an IRQ..

what?s all this about data rate? What is this all about?
I sended this

Code: Select all

out(0x3f7, 0)
in the beginning of the initialization. Then I send the stuff you told me when using the specify command. Do these values have to be something special, or will it work with several combinations? What are they for?
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Re:Using floppy disc

Post by Neo »

check the manual
Only Human
Brandon

Re:Using floppy disc

Post by Brandon »

Brendan:
Whats the CSH? And if I chose not to use DMA, how do I read the "next byte". I send a read command, wait for an IRC, but how do I recieve the next byte?

Can I only park the head at a cylinder and not "closer" to where I want?
Post Reply