floppy driver problems.

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.
Post Reply
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

floppy driver problems.

Post by 01000101 »

I just started to implement a long-mode floppy driver as I've been stuck using interrupts for a while whist I focused on other things.

I have been following the wiki article about floppy drivers and also mystran's tutorial thread, but I keep getting errors when I calibrate the floppy drive.

I first do a reset by clearing and then setting bit 2 in the DOR reg.
Then I clear the CCR register to set the drive for 500kb/s operation.
The function floppy_fix_drive_data() sets up function 0x03 with appropriate (i think) timings for the drive.
Then when I get to the recalibration function, I get errors from the check_interrupt_status function. It fails all 4 times with the same issues.

Here's the code for the critical parts, if you want to see more just ask.

Code: Select all

#define base_address        0x03f0
#define DOR_register        0x03f2
#define status_register     0x03f4
#define data_register       0x03f5
#define CCR_register        0x03f7

/* -- DOR Register Bits -- */
#define DR0     0x01
#define DR1     0x02
#define REST    0x04
#define DMA     0x08
#define MOTA    0x10
#define MOTB    0x20
#define MOTC    0x40
#define MATD    0x80

/* -- Main Status Register Bits -- */
#define ACTA    0x01
#define ACTB    0x02
#define ACTC    0x04
#define ACTD    0x08
#define BUSY    0x10
#define NDMA    0x20
#define DIO     0x40
#define MRQ     0x80

void wait_for_data()
{
    int timeout = 1000;
    while((inportb(status_register) & BUSY) != 0)
    {if(timeout){timeout--;wait(5);}else{break;}}
    if(!timeout){printf("fdc - wait_for_data timeout! \n");}
}

unsigned short floppy_check_interrupt_status()
{
    unsigned short ret_val = 0;
    while(1)
    {
        floppy_write_cmd(0x08);
        wait_for_data();
        ret_val = ((read_controller() << 8) & 0xFF00);
        if((ret_val & 0xFF00) != 0x8000)
        {
            wait_for_data();
            ret_val |= (read_controller() & 0xFF);
            break;
        }
    }
    printf("fdc - interrupt_status: %x \n", ret_val);
    return ret_val;
}

void floppy_recalibrate()
{
    int timeout = 4;
    turn_floppy_motor_on();
    
    while(timeout--)
    {
        floppy_write_cmd(0x07); // recalibrate cmd
        floppy_write_cmd(0x00);
        if((floppy_check_interrupt_status() & 0x1000) == 0){break;} // check the UC bit in ST0
    }
    turn_floppy_motor_off();
}

void floppy_fix_drive_data()
{
    turn_floppy_motor_on();
    floppy_write_cmd(0x03); // fix drive data cmd
    floppy_write_cmd(0x8f); /* steprate = 8ms, unload time = 240ms */
    floppy_write_cmd(0x0B); /* load time = 10ms, no-DMA = 1 */
    
    int timeout = 1000;
    while((inportb(status_register) & BUSY) != 0 || (inportb(DOR_register) & REST) == 0)
    {if(timeout){timeout--;wait(1);}else{break;}}
    if(!timeout){printf("fdc - fix_drive_data timeout! \n");}
    turn_floppy_motor_off();
}

void floppy_reset()
{ 
    outportb(DOR_register, 0x00);
    outportb(DOR_register, REST);
    
    int timeout = 1000;
    while((inportb(status_register) & BUSY) != 0 || (inportb(DOR_register) & REST) == 0)
    {if(timeout){timeout--;wait(5);}else{break;}}
    if(!timeout){printf("fdc - reset timeout! \n");}
    
    outportb(CCR_register, 0x00);   // 500kbits/s transfer rate
    
    floppy_fix_drive_data();
    floppy_recalibrate();
    floppy_check_drive_status();
}
in the end I get a bunch of "fdc - interrupt_status: 0x7000 " (ST0 = 0x70, CYL = 0x00)

any help is appreciated.
Last edited by 01000101 on Tue Sep 16, 2008 8:07 pm, edited 1 time in total.
User avatar
cr2
Member
Member
Posts: 162
Joined: Fri Jun 27, 2008 8:05 pm
Location: ND, USA

Re: floppy driver problems.

Post by cr2 »

Please list your #defines.
OS-LUX V0.0
Working on...
Memory management: the Pool
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: floppy driver problems.

Post by 01000101 »

ok, the orig post has been updated with the defines.
User avatar
cr2
Member
Member
Posts: 162
Joined: Fri Jun 27, 2008 8:05 pm
Location: ND, USA

Re: floppy driver problems.

Post by cr2 »

try using interrupts instead of polling.
OS-LUX V0.0
Working on...
Memory management: the Pool
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: floppy driver problems.

Post by 01000101 »

I could... except my entire OS is polling based, so that's not the best solution for me. Any actual ideas as to why the above code is failing the way it is?
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Re: floppy driver problems.

Post by Stevo14 »

The main thing that I see is that when you clear and reset the DOR, you are not setting the DMAGATE bit (bit 3). So it should look like:

Code: Select all

outportb(DOR_register, 0x00);
outportb(DOR_register, REST | DMA);//set bits 2 and 3
From the data sheet:
82077AA_FloppyControllerDatasheet wrote: If DMAGATE is set low the INT and DRQ outputs are tristated and the DACK and TC inputs are disabled. DMAGATE set high will enable INT DRQ TC and DACK to the system
This could be why you are getting errors.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: floppy driver problems.

Post by 01000101 »

I will test that out in a bit. Thanks.

But what if I don't want to use a DMA channel to conduct transactions? Would I still need to enable that bit regardless?
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: floppy driver problems.

Post by Dex »

You can take a look at my floppy driver, its well commented. http://dex4u.com/demos/FloppyDriver.zip

I use most poling in my OS, but for a floppy driver, its much better to use int and DMA.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: floppy driver problems.

Post by 01000101 »

thanks, I'll check it out.
I guess it's not that hard to implement DMA anyway.
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Re: floppy driver problems.

Post by Stevo14 »

Yes, that was my first intention as well (to stay away from DMA) but I had trouble getting it to read/send me the right amount of data through the fifo. So, in the end I settled for DMA. Either way, I'm pretty sure that DMAGATE needs to be high for both modes (there is a different DMA bit somewhere else that actually makes a difference... can't remember what it is right now. Have a look in the data sheet if you are interested.).
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: floppy driver problems.

Post by Dex »

I had the same idea when i started, i spent a week trying to get poling and nonDMA working.
In the end i changed to int and DMA and it worked fine.
Come to think about it i have not heard of anyone geting non-DMA floppy driver working, does anyone know of one ?.
bontanu
Member
Member
Posts: 134
Joined: Thu Aug 18, 2005 11:00 pm
Location: Sol. Earth. Europe. Romania. Bucuresti
Contact:

Re: floppy driver problems.

Post by bontanu »

Come to think about it i have not heard of anyone geting non-DMA floppy driver working, does anyone know of one ?.
Yes, I did make it work without DMA but I do know that hardware chip very well.

Initial SOLAR OS floppy driver was non-DMA. However later on I have switched to using DMA.

So, yes it is possible...
Ambition is a lame excuse for the ones not brave enough to be lazy; Solar_OS http://www.oby.ro/os/
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: floppy driver problems.

Post by Dex »

bontanu wrote:
Come to think about it i have not heard of anyone geting non-DMA floppy driver working, does anyone know of one ?.
Yes, I did make it work without DMA but I do know that hardware chip very well.

Initial SOLAR OS floppy driver was non-DMA. However later on I have switched to using DMA.

So, yes it is possible...
So it is possable, thanks for the info bontanu .
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: floppy driver problems.

Post by 01000101 »

good to know (about the DMA issue).

as far as my floppy driver... I must be making a very stupid mistake as I am getting interrupt statuses of 0x08 (not ready) and timeouts.

Code: Select all

void wait_for_controller_to_send_byte()
{
    unsigned int timeout = 1000;
    while(timeout--)
    {
        if((inportb(status_register) & 0xC0) == 0x80){return;}
        else{wait(240);}
    }
    printf("fdc - wait_for_controller_to_send_byte timeout! \n");
}

void wait_for_controller_to_get_byte()
{
    unsigned int timeout = 1000;
    while(timeout--)
    {
        if((inportb(status_register) & 0xC0) == 0xC0){return;}
        else{wait(240);}
    }
    printf("fdc - wait_for_controller_to_get_byte timeout! \n");
}

void floppy_send_byte(unsigned char data)
{
    wait_for_controller_to_send_byte();
    outportb(data_register, data);
}

unsigned char floppy_get_byte()
{
    wait_for_controller_to_get_byte();
    return inportb(data_register);
}

void wait_for_interrupt()
{
    unsigned int timeout = 100;
    while(timeout--)
    {
        floppy_send_byte(0x08);
        st0 = floppy_get_byte();
        cyl = floppy_get_byte();
        if(!(st0 & 0x80))
        {
            printf("fdc - interrupt: %x | %x \n", st0, cyl);
            return;
        }
        wait(5);
    }
    printf("fdc - interrupt timeout! \n");
}

void floppy_reset()
{
    floppy_motor_status = 0;
    st0 = st3 = cyl = 0;
    
    printf("fdc - resetting. \n");
    outportb(DOR_register, 0x00);       // Start Reset, DMA
    wait(250);
    outportb(DOR_register, 0x0C);       // Finish Reset, DMA
    wait(250);
    wait_for_interrupt();
    
    outportb(CCR_register, 0x00);       // 500Kb/s mode
    wait(250);
    
    printf("fdc - specify cmd. \n");
    floppy_send_byte(0x03);             // specify cmd
    floppy_send_byte(0xDF);             // SRT = 8ms, HUT = 240ms
    floppy_send_byte(0x02);             // HLT = 10ms, ND = 0
}
here, I get wait_for_controller_to_send_byte timeouts and invalid interrupt status returns (0x08). should I be waiting longer/shorter inbetween reset commands?
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Re: floppy driver problems.

Post by Stevo14 »

Hmm... Well, I noticed several other things that are different between what you have and what my floppy driver has.

First,
I can see that you are not issuing 4 "sense interrupt" commands to the drive after you program the data rate and before the specify command. According to the data sheet, the are required. Here is how I do it:

Code: Select all

for(i = 0; i < 4; i++)
{
    fdc_send_command(fd, FDC_SENSE_INTERRUPT);
    fdc_get_data(fd, &st0);
    fdc_get_data(fd, &cyl);
}
You can then optionally send the configure command before the specify command in order to configure the fifo, enable polling (not sure what this does exactly), and turn on implied seeks.

Code: Select all

//configure the drive
fdc_send_command(fd,FDC_CONFIGURE);
fdc_send_data(fd, 0x00);//this parameter is defined as all zeros for some reason
unsigned char config_bits = 
//                    7      6         5                 4          3   2   1   0
//the bits here are:| 0 |   EIS   |  EFIFO          |   POLL     | FIFO threshold |
                         (0 << 6) | (0 << 5)        | (1 << 4)   | 15;
//               No Implied Seeks | Enable the FIFO | No Polling | Large FIFO buffer |
fdc_send_data(fd, config_bits);
fdc_send_data(fd, 0);//pretrk
Other than that, your "wait for data" routines seem fine.

And for the legally paranoid among us, I release the above bits of code into the public domain. Do as you please with them.
Post Reply