Hard drive question

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
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Hard drive question

Post by frank »

The other day I decided to update my hard drive read and write functions. I decided to make them use interrupts instead of polling for data request. I have a question about when the ata controller fires an interrupt though. Right now my read hard drive function looks like this: ( I use PIO )

1. Write out sector number
2. Issue seek command
3. Wait for interrupt
4. Issue read command

5. Wait for interrupt
6. Read 1 sector
7. If we have not finished reading all sectors, go to 5

However, sometimes the int erupt for step 5 fails to come and my hard drive read function times out. I have 2 questions
1. Does the hard drive controller issue an interrupt for every sector read and
2. Does the above routine look okay, am I missing something.

Thanks,
Frank
Mikae
Member
Member
Posts: 94
Joined: Sun Jul 30, 2006 1:08 pm

Post by Mikae »

Do you check ERR and DF bit in status register after every interrupt? How do you poll your device, using status register or alternate status register? A read of status register clears interrupt pending state in a device, may be, it is a problem?
octavio
Member
Member
Posts: 94
Joined: Wed Oct 25, 2006 5:12 am
Location: Barcelona España
Contact:

Re: Hard drive question

Post by octavio »

frank wrote:The other day I decided to update my hard drive read and write functions. I decided to make them use interrupts instead of polling for data request. I have a question about when the ata controller fires an interrupt though. Right now my read hard drive function looks like this: ( I use PIO )

1. Write out sector number
2. Issue seek command
3. Wait for interrupt
4. Issue read command

5. Wait for interrupt
6. Read 1 sector
7. If we have not finished reading all sectors, go to 5

However, sometimes the int erupt for step 5 fails to come and my hard drive read function times out. I have 2 questions
1. Does the hard drive controller issue an interrupt for every sector read and
2. Does the above routine look okay, am I missing something.

Thanks,
Frank
I think it only fires interrupt if the drive become busy, but if data is already available then the driver must start the transfer without waiting for the interrupt, note also that after the transfer is complete another interrupt is generated.
The seek command is not needed.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Here is the code from the problem portion of the function

Code: Select all

// send the read command
outportb( base_port + 7, 0x20 );

// get a pointer to the buffer
WORD *read_buffer = (WORD *)buffers[ buf ].Get_Whole_Buffer( );

// read the data in 1 sector at a time
for ( i = 0; i < 64; i++ )
{
    // wait for the interupt to fire
    if ( !Wait_For_Interupt( irq_number, 5000 ) )
    {
        // release the mutex
        Release_Mutex( mutex );

        return( DISK_TIMEOUT_ERROR );

    } // end if

    // wait 1 PIO cycle
    inportb( base_port + 0x206 );

    // read from the status register
    UINT status = inportb( base_port + 7 );

    // check for error
    if ( status & 1 )
    {
        // release the mutex
        Release_Mutex( mutex );

        // return the error
        return ( ( inportb( base_port + 1 ) << 8 ) | DISK_DRIVE_ERROR );

    } // end if

    for ( int offset = 0; offset < 512 / 2; offset++ )
    {
        (*read_buffer) = inportw( base_port );
        read_buffer++;

    } // end for

} // end for

// check for an error
if ( inportb( base_port + 7 ) & 0x1 )
{
    // an error occured
    int error = inportb( base_port + 1 );

    // release the mutex
    Release_Mutex( mutex );

    // return error
    return( (error << 8 ) | DISK_DRIVE_ERROR );

} // end if
Wait for interrupt has the following takes the interrupt number and the maximum number of milliseconds to wait for the interrupt. Are you sure that the seek command is not needed, even on older hardware. By the way I only support drives with LBA addressing. I know that interrupts are enabled because I get one are the seek command.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

The reply above seems to be correct. You are reading the regular status port (base + 7). You need to be reading the ALTERNATE status port. For the moment, I can't find the port number, but it's in the documentation -- especially if you can read that wacky CS, DS assertion/negation table.

But the point is that a read from the regular status port will pre-empt an impending interrupt and keep it from ever happening.

Beyond that, yes, a disk will send an interrupt for every single sector, when the data is ready to read.

I think interrupts are time-wasters, so I'd rather not receive them. So I always pre-empt mine on purpose in PIO mode.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

bewing wrote:The reply above seems to be correct. You are reading the regular status port (base + 7). You need to be reading the ALTERNATE status port. For the moment, I can't find the port number, but it's in the documentation -- especially if you can read that wacky CS, DS assertion/negation table.
I thought that somewhere you had to read the main status register to clear the interrupt, and that if you did not clear the interrupt you would not be to receive any more interrupts from the drive controller.
ata reference wrote: The device shall exit the interrupt pending state when:
1) the device is selected, BSY is cleared to zero, and the Status register is read;
2) the device is selected, both BSY and DRQ are cleared to zero, and the Command register is
written;
3) the RESET- signal is asserted;
4) the SRST bit is set to one.
octavio
Member
Member
Posts: 94
Joined: Wed Oct 25, 2006 5:12 am
Location: Barcelona España
Contact:

Post by octavio »

I have done a HD driver for my OS and it do not uses the seek command,it works also on older disks using chs, i have tested disk from 1992.
Mi HD driver uses polling but the atapi driver uses interrupts, i do not use the
alternate status port, i send commands for reading multiple sectors ,then i wait for the first interrupt, read a sector and read the status byte , if busy then the driver waits for another interrupt, else it reads next sector.
did you send the ACK to the PIC ?
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

octavio wrote: did you send the ACK to the PIC ?
yes thats handled by the isr.

So after I read a sector, i should check to see if the drive is busy. If it is busy, then i should wait for another interupt, if it is not I should just go ahead and read the next sector?
Post Reply